Skip to content

Commit

Permalink
Active token for new scope after redirect to home #106
Browse files Browse the repository at this point in the history
  • Loading branch information
hupf committed Nov 6, 2023
1 parent c94da37 commit 7a613d6
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 2 deletions.
11 changes: 10 additions & 1 deletion src/components/Content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { keyed } from "lit/directives/keyed.js";
import { localized } from "@lit/localize";
import { theme } from "../utils/theme";
import { when } from "lit/directives/when.js";
import { getCurrentAccessToken } from "../utils/storage";
import { getTokenPayload, tokenMatchesScope } from "../utils/token";

Check failure on line 10 in src/components/Content.ts

View workflow job for this annotation

GitHub Actions / test (18)

'getTokenPayload' is defined but never used

@customElement("bkd-content")
@localized()
Expand Down Expand Up @@ -93,7 +95,14 @@ export class Content extends LitElement {
}

render() {
// The keyed directive ensures that the entire iframe and any associated scripts are removed when the application changes.
if (!tokenMatchesScope(getCurrentAccessToken(), portalState.app.scope)) {
// Token scope does not match current app, wait for correct
// token to be activated in <Portal> component
return html`<main></main>`;
}

// The keyed directive ensures that the entire iframe and any
// associated scripts are removed when the application changes.
return html`
<main>
${when(
Expand Down
18 changes: 18 additions & 0 deletions src/components/Portal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getCurrentAccessToken } from "../utils/storage";
import { settings } from "../settings";
import { getInitialLocale } from "../utils/locale";
import { getNavigationItemByAppPath } from "../utils/navigation.ts";
import { tokenMatchesScope } from "../utils/token.ts";

const oAuthClient = createOAuthClient();

Expand Down Expand Up @@ -78,6 +79,23 @@ export class Portal extends LitElement {
connectedCallback(): void {
super.connectedCallback();

portalState.initialized.then(() => {
// When all roles/permissions have been loaded and the current
// app does not match the scope of the current token, activate a
// token for the app's scope. This can be the case when
// previously authenticated as another user and the current user
// has no access to the navigation item from the redirect URL,
// hence is redirected to home (see
// https://github.com/bkd-mba-fbi/evento-portal/issues/106).
if (!tokenMatchesScope(getCurrentAccessToken(), portalState.app.scope)) {
activateTokenForScope(
oAuthClient,
portalState.app.scope,
portalState.locale,
);
}
});

this.subscriptions.push(
portalState.subscribeScopeAndLocale(
(scope, locale) => activateTokenForScope(oAuthClient, scope, locale),
Expand Down
2 changes: 1 addition & 1 deletion src/state/portal-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class PortalState extends State {
actualAppPath: string | null = null;

private setInitialized: () => void = () => undefined;
private initialized = new Promise(
initialized = new Promise(
(resolve) => (this.setInitialized = () => resolve(null)),
);

Expand Down
11 changes: 11 additions & 0 deletions src/utils/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ export function isTokenHalfExpired(
return expirationTime <= now + validFor / 2;
}

/**
* Returns whether the given token matches the given scope.
*/
export function tokenMatchesScope(
token: string | null,
scope: string,
): boolean {
const tokenScope = token && getTokenPayload(token).scope;
return tokenScope === scope;
}

function parseTokenPayload(token: string): RawTokenPayload {
const base64Url = token.split(".")[1];
const base64 = base64Url.replace("-", "+").replace("_", "/");
Expand Down

0 comments on commit 7a613d6

Please sign in to comment.