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

feat(scope): scope can be change dynamically #1489

Merged
merged 3 commits into from
Jan 3, 2025
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
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
Loading