Skip to content

Commit

Permalink
authn: Preserve original Cognito groups on user object
Browse files Browse the repository at this point in the history
This will make potential future user object updates in deserializeUser()
much easier because we won't have to figure out which old user
properties contain the "unparsed" or "original" array of Cognito groups
to re-parse.

Ultimately, it will still be better to move to storing the original id
and refresh tokens in the session instead of the user object.  The
deserializeUser() step would then reparse the id token (after
potentially refreshing it) every time and not have to worry about
upgrading a derived, persistent object.  I'm not sure when we'll get
around to that, however, so for now this bit of low-effort
future-proofing seems likely to be helpful.

Related to <#81>.
  • Loading branch information
tsibley committed Apr 7, 2022
1 parent 2eed398 commit 23ea98f
Showing 1 changed file with 15 additions and 2 deletions.
17 changes: 15 additions & 2 deletions src/authn/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,12 @@ function setup(app) {
}

const update = (originalCognitoGroups, reason) => {
const {groups, authzRoles, flags} = parseCognitoGroups(originalCognitoGroups);
const {groups, authzRoles, flags, cognitoGroups} = parseCognitoGroups(originalCognitoGroups);
utils.verbose(`Updating user object for ${user.username}: ${reason}`);
user.groups = groups;
user.authzRoles = authzRoles;
user.flags = flags;
user.cognitoGroups = cognitoGroups;
user[RESAVE_TO_SESSION] = true;
};

Expand All @@ -204,6 +205,11 @@ function setup(app) {
*/
if (!("flags" in user)) update([...user.authzRoles], "missing flags");

/* Future updates can pass user.cognitoGroups to update(). The updates
* above predate that property.
* -trs, 18 March 2022
*/

return done(null, user);
});

Expand Down Expand Up @@ -391,13 +397,14 @@ function setup(app) {
async function userFromIdToken(idToken, client = undefined) {
const idClaims = await verifyToken(idToken, "id", client);

const {groups, authzRoles, flags} = parseCognitoGroups(idClaims["cognito:groups"] || []);
const {groups, authzRoles, flags, cognitoGroups} = parseCognitoGroups(idClaims["cognito:groups"] || []);

const user = {
username: idClaims["cognito:username"],
groups,
authzRoles,
flags,
cognitoGroups,
};
return user;
}
Expand Down Expand Up @@ -448,6 +455,12 @@ function parseCognitoGroups(cognitoGroups) {
.filter(g => g.startsWith("!flags/"))
.map(g => g.replace(/^!flags\//, ""))
),

/* Preserving the original groups helps us just-in-time upgrade the user
* object later (e.g. in deserializeUser) by calling (the updated version
* of) this function again with this (original) array.
*/
cognitoGroups,
};
}

Expand Down

0 comments on commit 23ea98f

Please sign in to comment.