Skip to content

Commit

Permalink
feat(oidc): logout add extras parameter to avoid the page reload (rel…
Browse files Browse the repository at this point in the history
…ease) (#1290)

* feat(oidc): logout add extras parameter to avoid the page reload after logout.

* update demo

* update
  • Loading branch information
guillaume-chervet authored Feb 10, 2024
1 parent fbb7111 commit a09e6fd
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 12 deletions.
1 change: 1 addition & 0 deletions examples/react-oidc-demo/src/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const Home = () => {
{!isAuthenticated && <p><button type="button" className="btn btn-primary" onClick={() => login('/profile')}>Login</button></p>}
{isAuthenticated && <p><button type="button" className="btn btn-primary" onClick={() => logout('/profile')}>logout /profile</button></p>}
{isAuthenticated && <p><button type="button" className="btn btn-primary" onClick={() => logout()}>logout</button></p>}
{isAuthenticated && <p><button type="button" className="btn btn-primary" onClick={() => logout(null, {"no_reload:oidc":"true"})}>logout no reload</button></p>}
{isAuthenticated && <p><button type="button" className="btn btn-primary" onClick={() => logout(null)}>logout whithout callbackredirect</button></p>}
{isAuthenticated && <p><button type="button" className="btn btn-primary" onClick={async () => console.log('renewTokens result', await renewTokens())}>renew tokens</button></p>}
<p><button type="button" className="btn btn-primary" onClick={navigateProfile}>Navigate to profile</button></p>
Expand Down
2 changes: 1 addition & 1 deletion packages/oidc-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ export class OidcClient {
/**
* Starts the OIDC logout process with specified options.
* @param callbackPathOrUrl The callback path or URL to use after logout.
* @param extras Additional parameters to send to the OIDC server during the logout request.
* @param extras Additional parameters to send to the OIDC server during the logout request. {"no_reload:oidc":"true"} to avoid the page reload after logout.
* @returns A promise resolved when the logout is completed.
*/
logoutAsync(callbackPathOrUrl?: string | null | undefined, extras?: StringMap): Promise<void>;
Expand Down
17 changes: 9 additions & 8 deletions packages/oidc-client/src/logout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import { logoutAsync } from "./logout";
import {ILOidcLocation, OidcLocation} from "./location";

describe('Logout test suite', () => {

const expectedFinalUrl = "http://api/connect/endsession?id_token_hint=abcd&post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Flogged_out";
it.each([
{logout_tokens_to_invalidate:['access_token', 'refresh_token'], expectedResults: ["token=abcd&token_type_hint=access_token&client_id=interactive.public.short","token=abdc&token_type_hint=refresh_token&client_id=interactive.public.short"]},
{logout_tokens_to_invalidate:['refresh_token'], expectedResults: ["token=abdc&token_type_hint=refresh_token&client_id=interactive.public.short"]},
{logout_tokens_to_invalidate:['access_token'], expectedResults: ["token=abcd&token_type_hint=access_token&client_id=interactive.public.short"]},
{logout_tokens_to_invalidate:[], expectedResults: []},
])('Logout should revoke tokens $logout_tokens_to_invalidate', async ({ logout_tokens_to_invalidate, expectedResults}) => {
{logout_tokens_to_invalidate:['access_token', 'refresh_token'], extras:null, expectedResults: ["token=abcd&token_type_hint=access_token&client_id=interactive.public.short","token=abdc&token_type_hint=refresh_token&client_id=interactive.public.short"], expectedFinalUrl},
{logout_tokens_to_invalidate:['refresh_token'],extras:null, expectedResults: ["token=abdc&token_type_hint=refresh_token&client_id=interactive.public.short"], expectedFinalUrl},
{logout_tokens_to_invalidate:['access_token'],extras:null, expectedResults: ["token=abcd&token_type_hint=access_token&client_id=interactive.public.short"], expectedFinalUrl},
{logout_tokens_to_invalidate:[],extras:null, expectedResults: [], expectedFinalUrl},
{logout_tokens_to_invalidate:[],extras: {"no_reload:oidc":"true"}, expectedResults: [], expectedFinalUrl:""},
])('Logout should revoke tokens $logout_tokens_to_invalidate', async ({ logout_tokens_to_invalidate, extras =null, expectedResults, expectedFinalUrl}) => {

const configuration = {
client_id: 'interactive.public.short',
Expand Down Expand Up @@ -70,13 +71,13 @@ describe('Logout test suite', () => {

}

await logoutAsync(oidc, oidcDatabase, mockFetchFn, console, new OidcLocationMock())("/logged_out");
await logoutAsync(oidc, oidcDatabase, mockFetchFn, console, new OidcLocationMock())("/logged_out", extras);

// @ts-ignore

const results = mockFetchFn.mock.calls.map((call, index) => call[1].body);

expect(results).toEqual(expectedResults);
expect(finalUrl).toBe("http://api/connect/endsession?id_token_hint=abcd&post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Flogged_out");
expect(finalUrl).toBe(expectedFinalUrl);
});
});
17 changes: 16 additions & 1 deletion packages/oidc-client/src/logout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const logoutAsync = (oidc, oidcDatabase, fetch, console, oicLocation:ILOi
const sub = oidc.tokens && oidc.tokens.idTokenPayload ? oidc.tokens.idTokenPayload.sub : null;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
await oidc.destroyAsync('LOGGED_OUT');
for (const [key, itemOidc] of Object.entries(oidcDatabase)) {
if (itemOidc !== oidc) {
// @ts-ignore
Expand All @@ -77,7 +78,21 @@ export const logoutAsync = (oidc, oidcDatabase, fetch, console, oicLocation:ILOi
oidc.publishEvent(eventNames.logout_from_same_tab, {} );
}
}
await oidc.destroyAsync('LOGGED_OUT');

let noReload = false;
if(extras) {
extras = {...extras};
for (const [key, value] of Object.entries(extras)) {
if (key.endsWith('no_reload:oidc')) {
noReload = extras[key] == "true";
delete extras[key];
}
}
}

if(noReload) {
return;
}

if (oidcServerConfiguration.endSessionEndpoint) {
if (!extras) {
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 @@ -366,16 +366,16 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
async logoutSameTabAsync(clientId: string, sub: any) {
// @ts-ignore
if (this.configuration.monitor_session && this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
this.publishEvent(eventNames.logout_from_same_tab, { mmessage: 'SessionMonitor', sub });
await this.destroyAsync('LOGGED_OUT');
this.publishEvent(eventNames.logout_from_same_tab, { mmessage: 'SessionMonitor', sub });
}
}

async logoutOtherTabAsync(clientId: string, sub: any) {
// @ts-ignore
if (this.configuration.monitor_session && this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
this.publishEvent(eventNames.logout_from_another_tab, { message: 'SessionMonitor', sub });
await this.destroyAsync('LOGGED_OUT');
this.publishEvent(eventNames.logout_from_another_tab, { message: 'SessionMonitor', sub });
}
}

Expand Down

0 comments on commit a09e6fd

Please sign in to comment.