Finish implementing token refresh.

This implementation just keeps the refresh token and only updates the
access token. The spec says that this is allowed. There's really no
reason to do this, other than the fact that it's easier.
This commit is contained in:
Jordan Bancino 2023-02-17 03:20:49 +00:00
parent 4b336de171
commit ff879e715f
2 changed files with 43 additions and 5 deletions

View file

@ -13,9 +13,9 @@ Milestone: v0.2.0
[ ] Abstract /email/requestToken and /msidsn/requestToken [ ] Abstract /email/requestToken and /msidsn/requestToken
[ ] User login [~] User login
[ ] User manipulation functions (so we don't use the DB directly) [x] User manipulation functions (so we don't use the DB directly)
[ ] Refresh tokens [x] Refresh tokens
[ ] Logout [ ] Logout
[ ] Logout all [ ] Logout all
[ ] Login fallback (static HTML page) [ ] Login fallback (static HTML page)
@ -31,6 +31,8 @@ Milestone: v0.2.0
[x] Document User [x] Document User
[x] Document Str and remove old functions from Util docs. [x] Document Str and remove old functions from Util docs.
[x] Move docs from Matrix to User for UserValidate [x] Move docs from Matrix to User for UserValidate
[ ] Document HashMapGetKey()
[ ] Document new User functions
[ ] Document new JSON functions [ ] Document new JSON functions
[ ] Document UserInteractiveAuth (move docs from Matrix) [ ] Document UserInteractiveAuth (move docs from Matrix)

View file

@ -30,6 +30,8 @@
#include <HashMap.h> #include <HashMap.h>
#include <Str.h> #include <Str.h>
#include <User.h>
ROUTE_IMPL(RouteRefresh, args) ROUTE_IMPL(RouteRefresh, args)
{ {
HashMap *request; HashMap *request;
@ -39,15 +41,15 @@ ROUTE_IMPL(RouteRefresh, args)
char *refreshToken; char *refreshToken;
char *oldAccessToken; char *oldAccessToken;
char *newAccessToken; UserAccessToken *newAccessToken;
char *deviceId; char *deviceId;
Db *db = args->matrixArgs->db; Db *db = args->matrixArgs->db;
LogConfig *lc = args->matrixArgs->lc; LogConfig *lc = args->matrixArgs->lc;
User *user = NULL;
DbRef *rtRef = NULL; DbRef *rtRef = NULL;
DbRef *oAtRef = NULL; DbRef *oAtRef = NULL;
DbRef *nAtRef = NULL;
if (MATRIX_PATH_PARTS(args->path) > 0) if (MATRIX_PATH_PARTS(args->path) > 0)
{ {
@ -103,24 +105,58 @@ ROUTE_IMPL(RouteRefresh, args)
DbUnlock(db, rtRef); DbUnlock(db, rtRef);
DbDelete(db, 3, "tokens", "refresh", refreshToken); DbDelete(db, 3, "tokens", "refresh", refreshToken);
rtRef = NULL;
goto finish; goto finish;
} }
/* Get the user associated with the access token and device */ /* Get the user associated with the access token and device */
user = UserLock(db, JsonValueAsString(HashMapGet(DbJson(oAtRef), "user")));
if (!user)
{
Log(lc, LOG_ERR, "Access token '%s' points to a user that doesn't exist.",
oldAccessToken);
Log(lc, LOG_WARNING, "This access token will be deleted.");
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
response = MatrixErrorCreate(M_UNKNOWN);
DbUnlock(db, rtRef);
DbDelete(db, 3, "tokens", "refresh", refreshToken);
DbUnlock(db, oAtRef);
DbDelete(db, 3, "tokens", "access", oldAccessToken);
rtRef = NULL;
oAtRef = NULL;
goto finish;
}
/* Generate a new access token associated with the device and user. */ /* Generate a new access token associated with the device and user. */
deviceId = JsonValueAsString(HashMapGet(DbJson(oAtRef), "device"));
newAccessToken = UserGenerateAccessToken(user, deviceId, 1);
UserAccessTokenSave(db, newAccessToken);
/* Replace old access token in User */ /* Replace old access token in User */
JsonValueFree(JsonSet(UserGetDevices(user), JsonValueString(newAccessToken->string), 2, deviceId, "accessToken"));
/* Delete old access token */ /* Delete old access token */
DbUnlock(db, oAtRef);
DbDelete(db, 3, "tokens", "access", oldAccessToken);
/* Update the refresh token to point to the new access token */ /* Update the refresh token to point to the new access token */
JsonValueFree(HashMapSet(DbJson(rtRef), "refreshes", JsonValueString(StrDuplicate(newAccessToken->string))));
/* Return the new access token and expiration timestamp to the client */ /* Return the new access token and expiration timestamp to the client */
response = HashMapCreate(); response = HashMapCreate();
HashMapSet(response, "access_token", JsonValueString(StrDuplicate(newAccessToken->string)));
HashMapSet(response, "expires_in_ms", JsonValueInteger(newAccessToken->lifetime));
Free(newAccessToken);
finish: finish:
JsonFree(request); JsonFree(request);
DbUnlock(db, rtRef); DbUnlock(db, rtRef);
UserUnlock(user);
return response; return response;
} }