Skip to content

Commit

Permalink
feat(scope): scope can be change dynamically (release) (#1489)
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaume-chervet committed Jan 3, 2025
1 parent f742c6a commit de5da36
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 31 deletions.
5 changes: 3 additions & 2 deletions examples/react-oidc-demo/public/OidcTrustedDomains.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/react-oidc-demo/src/MultiAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const MultiAuth = ({ configurationName, handleConfigurationChange }) => {
tenantId: '1234',
},
true,
'openid profile email',
)
}
>
Expand Down
42 changes: 33 additions & 9 deletions packages/oidc-client-service-worker/src/OidcServiceWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,14 @@ async function generateDpopAsync(
) {
const dpopConfiguration = currentDatabase.demonstratingProofOfPossessionConfiguration;
const jwk = currentDatabase.demonstratingProofOfPossessionJwkJson;
headersExtras['dpop'] = await generateJwtDemonstratingProofOfPossessionAsync(self)(
dpopConfiguration,
)(jwk, 'POST', url, extrasClaims);
const method = originalRequest.method;
const dpop = await generateJwtDemonstratingProofOfPossessionAsync(self)(dpopConfiguration)(
jwk,
method,
url,
extrasClaims,
);
headersExtras['dpop'] = dpop;
if (currentDatabase.demonstratingProofOfPossessionNonce != null) {
headersExtras['nonce'] = currentDatabase.demonstratingProofOfPossessionNonce;
}
Expand Down Expand Up @@ -127,7 +132,6 @@ const handleFetch = async (event: FetchEvent) => {
) {
requestMode = 'cors';
}

let headers: { [p: string]: string };
if (
originalRequest.mode == 'navigate' &&
Expand All @@ -142,11 +146,31 @@ const handleFetch = async (event: FetchEvent) => {
if (authorization) {
authenticationMode = authorization.split(' ')[0];
}
headers = {
...serializeHeaders(originalRequest.headers),
authorization:
authenticationMode + ' ' + currentDatabaseForRequestAccessToken.tokens.access_token,
};

if (authenticationMode.toLowerCase() == 'dpop') {
const claimsExtras = {
ath: await base64urlOfHashOfASCIIEncodingAsync(
currentDatabaseForRequestAccessToken.tokens.access_token,
),
};
const dpopHeaders = await generateDpopAsync(
originalRequest,
currentDatabaseForRequestAccessToken,
url,
claimsExtras,
);
headers = {
...dpopHeaders,
authorization:
authenticationMode + ' ' + currentDatabaseForRequestAccessToken.tokens.access_token,
};
} else {
headers = {
...serializeHeaders(originalRequest.headers),
authorization:
authenticationMode + ' ' + currentDatabaseForRequestAccessToken.tokens.access_token,
};
}
}
let init: RequestInit;
if (originalRequest.mode === 'navigate') {
Expand Down
4 changes: 2 additions & 2 deletions packages/oidc-client/src/oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio

renewTokensPromise: Promise<any> = null;

async renewTokensAsync(extras: StringMap = null) {
async renewTokensAsync(extras: StringMap = null, scope: string = null) {
if (this.renewTokensPromise !== null) {
return this.renewTokensPromise;
}
Expand All @@ -427,7 +427,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
}
timer.clearTimeout(this.timeoutId);
// @ts-ignore
this.renewTokensPromise = renewTokensAndStartTimerAsync(this, true, extras);
this.renewTokensPromise = renewTokensAndStartTimerAsync(this, true, extras, scope);
return this.renewTokensPromise.finally(() => {
this.renewTokensPromise = null;
});
Expand Down
4 changes: 2 additions & 2 deletions packages/oidc-client/src/oidcClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ export class OidcClient {
return this._oidc.silentLoginCallbackAsync();
}

renewTokensAsync(extras: StringMap = null): Promise<void> {
return this._oidc.renewTokensAsync(extras);
renewTokensAsync(extras: StringMap = null, scope: string = null): Promise<void> {
return this._oidc.renewTokensAsync(extras, scope);
}

loginCallbackAsync(): Promise<LoginCallback> {
Expand Down
50 changes: 38 additions & 12 deletions packages/oidc-client/src/renewTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import { _silentLoginAsync } from './silentLogin';
import timer from './timer.js';
import { OidcConfiguration, StringMap, TokenAutomaticRenewMode } from './types.js';

async function syncTokens(oidc: Oidc, forceRefresh: boolean, extras: StringMap) {
async function syncTokens(
oidc: Oidc,
forceRefresh: boolean,
extras: StringMap,
scope: string = null,
) {
const updateTokens = tokens => {
oidc.tokens = tokens;
};
Expand All @@ -17,6 +22,7 @@ async function syncTokens(oidc: Oidc, forceRefresh: boolean, extras: StringMap)
0,
forceRefresh,
extras,
scope,
);

const serviceWorker = await initWorkerAsync(oidc.configuration, oidc.configurationName);
Expand All @@ -36,6 +42,7 @@ export async function renewTokensAndStartTimerAsync(
oidc,
forceRefresh = false,
extras: StringMap = null,
scope: string = null,
) {
const configuration = oidc.configuration;
const lockResourcesName = `${configuration.client_id}_${oidc.configurationName}_${configuration.authority}`;
Expand All @@ -44,7 +51,7 @@ export async function renewTokensAndStartTimerAsync(
const serviceWorker = await initWorkerAsync(oidc.configuration, oidc.configurationName);

if ((configuration?.storage === window?.sessionStorage && !serviceWorker) || !navigator.locks) {
tokens = await syncTokens(oidc, forceRefresh, extras);
tokens = await syncTokens(oidc, forceRefresh, extras, scope);
} else {
let status: any = 'retry';
while (status === 'retry') {
Expand All @@ -58,7 +65,7 @@ export async function renewTokensAndStartTimerAsync(
});
return 'retry';
}
return await syncTokens(oidc, forceRefresh, extras);
return await syncTokens(oidc, forceRefresh, extras, scope);
},
);
}
Expand All @@ -71,13 +78,18 @@ export async function renewTokensAndStartTimerAsync(

if (oidc.timeoutId) {
// @ts-ignore
oidc.timeoutId = autoRenewTokens(oidc, oidc.tokens.expiresAt, extras);
oidc.timeoutId = autoRenewTokens(oidc, oidc.tokens.expiresAt, extras, scope);
}

return oidc.tokens;
}

export const autoRenewTokens = (oidc: Oidc, expiresAt, extras: StringMap = null) => {
export const autoRenewTokens = (
oidc: Oidc,
expiresAt,
extras: StringMap = null,
scope: string = null,
) => {
const refreshTimeBeforeTokensExpirationInSecond =
oidc.configuration.refresh_time_before_tokens_expiration_in_second;
if (oidc.timeoutId) {
Expand All @@ -87,7 +99,7 @@ export const autoRenewTokens = (oidc: Oidc, expiresAt, extras: StringMap = null)
const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
const timeInfo = { timeLeft };
oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
await renewTokensAndStartTimerAsync(oidc, false, extras);
await renewTokensAndStartTimerAsync(oidc, false, extras, scope);
}, 1000);
};

Expand Down Expand Up @@ -186,7 +198,13 @@ export const syncTokensInfoAsync =

const synchroniseTokensAsync =
(oidc: Oidc) =>
async (updateTokens, index = 0, forceRefresh = false, extras: StringMap = null) => {
async (
updateTokens,
index = 0,
forceRefresh = false,
extras: StringMap = null,
scope: string = null,
) => {
if (!navigator.onLine && document.hidden) {
return { tokens: oidc.tokens, status: 'GIVE_UP' };
}
Expand All @@ -211,7 +229,7 @@ const synchroniseTokensAsync =
oidc.publishEvent.bind(oidc),
)(extras, state, scope);
};
const localsilentLoginAsync = async () => {
const localSilentLoginAsync = async () => {
try {
let loginParams;
const serviceWorker = await initWorkerAsync(configuration, oidc.configurationName);
Expand All @@ -225,6 +243,7 @@ const synchroniseTokensAsync =
...loginParams.extras,
...extras,
prompt: 'none',
scope,
});
if (!silent_token_response) {
updateTokens(null);
Expand All @@ -250,7 +269,13 @@ const synchroniseTokensAsync =
message: 'exceptionSilent',
exception: exceptionSilent.message,
});
return await synchroniseTokensAsync(oidc)(updateTokens, nextIndex, forceRefresh, extras);
return await synchroniseTokensAsync(oidc)(
updateTokens,
nextIndex,
forceRefresh,
extras,
scope,
);
}
};

Expand Down Expand Up @@ -297,7 +322,7 @@ const synchroniseTokensAsync =
}

oidc.publishEvent(eventNames.refreshTokensAsync_begin, { tryNumber: index });
return await localsilentLoginAsync();
return await localSilentLoginAsync();
default: {
if (
configuration.token_automatic_renew_mode ==
Expand All @@ -314,7 +339,7 @@ const synchroniseTokensAsync =
tryNumber: index,
});
if (!tokens.refreshToken) {
return await localsilentLoginAsync();
return await localSilentLoginAsync();
}

const clientId = configuration.client_id;
Expand Down Expand Up @@ -412,6 +437,7 @@ const synchroniseTokensAsync =
nextIndex,
forceRefresh,
extras,
scope,
);
}
};
Expand All @@ -429,7 +455,7 @@ const synchroniseTokensAsync =
// so we need to brake calls chain and delay next call
return new Promise((resolve, reject) => {
setTimeout(() => {
synchroniseTokensAsync(oidc)(updateTokens, nextIndex, forceRefresh, extras)
synchroniseTokensAsync(oidc)(updateTokens, nextIndex, forceRefresh, extras, scope)
.then(resolve)
.catch(reject);
}, 1000);
Expand Down
8 changes: 4 additions & 4 deletions packages/oidc-client/src/silentLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const _silentLoginAsync =
extras.state = state;
}

if (scope) {
if (scope != null) {
if (extras == null) {
extras = {};
}
Expand Down Expand Up @@ -136,11 +136,11 @@ export const defaultSilentLoginAsync =
(extras: StringMap = null, scope: string = undefined) => {
extras = { ...extras };

const silentLoginAsync = (extras, state, scope) => {
const silentLoginAsync = (extras, state, scopeInternal) => {
return _silentLoginAsync(configurationName, configuration, publishEvent.bind(oidc))(
extras,
state,
scope,
scopeInternal,
);
};

Expand Down Expand Up @@ -170,7 +170,7 @@ export const defaultSilentLoginAsync =
oidc.tokens = silentResult.tokens;
publishEvent(eventNames.token_acquired, {});
// @ts-ignore
oidc.timeoutId = autoRenewTokens(oidc, oidc.tokens.expiresAt, extras);
oidc.timeoutId = autoRenewTokens(oidc, oidc.tokens.expiresAt, extras, scope);
return {};
}
} catch (e) {
Expand Down

0 comments on commit de5da36

Please sign in to comment.