Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STCOR-776 RTR adjustments for keycloak #1490

Merged
merged 1 commit into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/components/Root/FFetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,20 @@ export class FFetch {

// When starting a new session, the response from /bl-users/login-with-expiry
// will contain AT expiration info, but when restarting an existing session,
// the response from /bl-users/_self will NOT, although that information will
// the response from /bl-users/_self will NOT, although that information should
// have been cached in local-storage.
//
// This means there are many places we have to check to figure out when the
// AT is likely to expire, and thus when we want to rotate. First inspect
// the response, otherwise the session. Default to 10 seconds.
// the response, then the session, then default to 10 seconds.
if (res?.accessTokenExpiration) {
this.logger.log('rtr', 'rotation scheduled with login response data');
const rotationPromise = Promise.resolve((new Date(res.accessTokenExpiration).getTime() - Date.now()) * RTR_AT_TTL_FRACTION);

scheduleRotation(rotationPromise);
} else {
const rotationPromise = getTokenExpiry().then((expiry) => {
if (expiry.atExpires) {
if (expiry?.atExpires) {
this.logger.log('rtr', 'rotation scheduled with cached session data');
return (new Date(expiry.atExpires).getTime() - Date.now()) * RTR_AT_TTL_FRACTION;
}
Expand Down Expand Up @@ -189,7 +189,12 @@ export class FFetch {
if (clone.ok) {
this.logger.log('rtr', 'authn success!');
clone.json().then(json => {
this.rotateCallback(json.tokenExpiration);
// we want accessTokenExpiration. do we need to destructure?
// in community-folio, a /login-with-expiry response is shaped like
// { ..., tokenExpiration: { accessTokenExpiration, refreshTokenExpiration } }
// in eureka-folio, a /authn/token response is shaped like
// { accessTokenExpiration, refreshTokenExpiration }
this.rotateCallback(json.tokenExpiration ?? json);
});
}

Expand Down
31 changes: 23 additions & 8 deletions src/loginServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -421,16 +421,31 @@ export function spreadUserWithPerms(userWithPerms) {
...userWithPerms?.user?.personal,
};

// remap userWithPerms.permissions.permissions from an array shaped like
// [{ "permissionName": "foo", ... }]
// to an object shaped like
// { foo: true, ...}
const perms = {};
// remap data's array of permission-names to set with
// permission-names for keys and `true` for values.
//
// userWithPerms is shaped differently depending on the API call
// that generated it.
// in community-folio, /login sends data like [{ "permissionName": "foo" }]
// and includes both directly and indirectly assigned permissions
// in community-folio, /_self sends data like ["foo", "bar", "bat"]
// but only includes directly assigned permissions
// in community-folio, /_self?expandPermissions=true sends data like [{ "permissionName": "foo" }]
// and includes both directly and indirectly assigned permissions
// in eureka-folio, /_self sends data like ["foo", "bar", "bat"]
// and includes both directly and indirectly assigned permissions
//
// we'll parse it differently depending on what it looks like.
let perms = {};
const list = userWithPerms?.permissions?.permissions;
if (list && Array.isArray(list) && list.length > 0) {
list.forEach(p => {
perms[p.permissionName] = true;
});
// shaped like this ["foo", "bar", "bat"] or
// shaped like that [{ "permissionName": "foo" }]?
if (typeof list[0] === 'string') {
perms = Object.assign({}, ...list.map(p => ({ [p]: true })));
} else {
perms = Object.assign({}, ...list.map(p => ({ [p.permissionName]: true })));
}
}

return { user, perms };
Expand Down
Loading