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

Add support for id_token_hint parameter in prompt=none requests #610

Closed
wants to merge 4 commits into from
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ node_modules/
.vscode/
temp/
.history/
.idea
*.iml
7 changes: 7 additions & 0 deletions docs/oidc-client-ts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,8 @@ export class UserManager {
signinPopupCallback(url?: string, keepOpen?: boolean): Promise<void>;
signinRedirect(args?: SigninRedirectArgs): Promise<void>;
signinRedirectCallback(url?: string): Promise<User>;
// (undocumented)
signInRequestArgsForPromptNone(): Promise<SigninRequestArgs>;
signinSilent(args?: SigninSilentArgs): Promise<User | null>;
signinSilentCallback(url?: string): Promise<void>;
// Warning: (ae-forgotten-export) The symbol "NavigateResponse" needs to be exported by the entry point index.d.ts
Expand Down Expand Up @@ -941,6 +943,8 @@ export class UserManagerEvents extends AccessTokenEvents {
addSilentRenewError(cb: SilentRenewErrorCallback): () => void;
addUserLoaded(cb: UserLoadedCallback): () => void;
addUserSessionChanged(cb: UserSessionChangedCallback): () => void;
// Warning: (ae-forgotten-export) The symbol "UserSessionErrorCallback" needs to be exported by the entry point index.d.ts
addUserSessionError(cb: UserSessionErrorCallback): () => void;
addUserSignedIn(cb: UserSignedInCallback): () => void;
addUserSignedOut(cb: UserSignedOutCallback): () => void;
addUserUnloaded(cb: UserUnloadedCallback): () => void;
Expand All @@ -953,12 +957,15 @@ export class UserManagerEvents extends AccessTokenEvents {
// @internal (undocumented)
_raiseUserSessionChanged(): void;
// @internal (undocumented)
_raiseUserSessionError(): void;
// @internal (undocumented)
_raiseUserSignedIn(): void;
// @internal (undocumented)
_raiseUserSignedOut(): void;
removeSilentRenewError(cb: SilentRenewErrorCallback): void;
removeUserLoaded(cb: UserLoadedCallback): void;
removeUserSessionChanged(cb: UserSessionChangedCallback): void;
removeUserSessionError(cb: UserSessionErrorCallback): void;
removeUserSignedIn(cb: UserSignedInCallback): void;
removeUserSignedOut(cb: UserSignedOutCallback): void;
removeUserUnloaded(cb: UserUnloadedCallback): void;
Expand Down
4 changes: 3 additions & 1 deletion src/SessionMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Logger } from "./utils";
import { CheckSessionIFrame } from "./CheckSessionIFrame";
import type { UserManager } from "./UserManager";
import type { User } from "./User";
import type {SigninRequestArgs} from "./SigninRequest";

/**
* @public
Expand Down Expand Up @@ -145,7 +146,8 @@ export class SessionMonitor {
protected _callback = async (): Promise<void> => {
const logger = this._logger.create("_callback");
try {
const session = await this._userManager.querySessionStatus();
const signRequestArgs: SigninRequestArgs = await this._userManager.signInRequestArgsForPromptNone();
const session = await this._userManager.querySessionStatus(signRequestArgs);
let raiseEvent = true;

if (session && this._checkSessionIFrame) {
Expand Down
40 changes: 24 additions & 16 deletions src/UserManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

import { Logger } from "./utils";
import { ErrorResponse } from "./errors";
import { IFrameNavigator, NavigateResponse, PopupNavigator, RedirectNavigator, PopupWindowParams,
IWindow, IFrameWindowParams, RedirectParams } from "./navigators";
import {
IFrameNavigator, NavigateResponse, PopupNavigator, RedirectNavigator, PopupWindowParams,
IWindow, IFrameWindowParams, RedirectParams,
} from "./navigators";
import { OidcClient, CreateSigninRequestArgs, CreateSignoutRequestArgs } from "./OidcClient";
import { UserManagerSettings, UserManagerSettingsStore } from "./UserManagerSettings";
import { User } from "./User";
Expand All @@ -15,6 +17,7 @@ import type { SessionStatus } from "./SessionStatus";
import type { SignoutResponse } from "./SignoutResponse";
import type { MetadataService } from "./MetadataService";
import { RefreshState } from "./RefreshState";
import type { SigninRequestArgs } from "./SigninRequest";

/**
* @public
Expand Down Expand Up @@ -163,8 +166,7 @@ export class UserManager {
const user = await this._signinEnd(url);
if (user.profile && user.profile.sub) {
logger.info("success, signed in subject", user.profile.sub);
}
else {
} else {
logger.info("no subject");
}

Expand Down Expand Up @@ -196,14 +198,14 @@ export class UserManager {
if (user) {
if (user.profile && user.profile.sub) {
logger.info("success, signed in subject", user.profile.sub);
}
else {
} else {
logger.info("no subject");
}
}

return user;
}

/**
* Returns promise to notify the opening window of response from the authorization endpoint.
*/
Expand Down Expand Up @@ -253,8 +255,7 @@ export class UserManager {
if (user) {
if (user.profile?.sub) {
logger.info("success, signed in subject", user.profile.sub);
}
else {
} else {
logger.info("no subject");
}
}
Expand Down Expand Up @@ -315,6 +316,13 @@ export class UserManager {
}
}

async signInRequestArgsForPromptNone(): Promise<SigninRequestArgs> {
const signInRequestArgs: SigninRequestArgs = Object.create({});
const user: User = await this.getUser() as User;
signInRequestArgs.id_token_hint = user.id_token;
return signInRequestArgs;
}

/**
* Returns promise to query OP for user's current signin status. Returns object with session_state and subject identifier.
*/
Expand Down Expand Up @@ -354,8 +362,7 @@ export class UserManager {

logger.info("success, user not authenticated");
return null;
}
catch (err) {
} catch (err) {
if (this.settings.monitorAnonymousSession && err instanceof ErrorResponse) {
switch (err.error) {
case "login_required":
Expand All @@ -377,6 +384,7 @@ export class UserManager {
const navResponse = await this._signinStart(args, handle);
return await this._signinEnd(navResponse.url, verifySub);
}

protected async _signinStart(args: CreateSigninRequestArgs, handle: IWindow): Promise<NavigateResponse> {
const logger = this._logger.create("_signinStart");

Expand All @@ -390,13 +398,13 @@ export class UserManager {
response_mode: signinRequest.state.response_mode,
scriptOrigin: this.settings.iframeScriptOrigin,
});
}
catch (err) {
} catch (err) {
logger.debug("error after preparing navigator, closing navigator window");
handle.close();
throw err;
}
}

protected async _signinEnd(url: string, verifySub?: string): Promise<User> {
const logger = this._logger.create("_signinEnd");
const signinResponse = await this._client.processSigninResponse(url);
Expand Down Expand Up @@ -486,6 +494,7 @@ export class UserManager {
const navResponse = await this._signoutStart(args, handle);
return await this._signoutEnd(navResponse.url);
}

protected async _signoutStart(args: CreateSignoutRequestArgs = {}, handle: IWindow): Promise<NavigateResponse> {
const logger = this._logger.create("_signoutStart");

Expand Down Expand Up @@ -513,13 +522,13 @@ export class UserManager {
url: signoutRequest.url,
state: signoutRequest.state?.id,
});
}
catch (err) {
} catch (err) {
logger.debug("error after preparing navigator, closing navigator window");
handle.close();
throw err;
}
}

protected async _signoutEnd(url: string): Promise<SignoutResponse> {
const logger = this._logger.create("_signoutEnd");
const signoutResponse = await this._client.processSignoutResponse(url);
Expand Down Expand Up @@ -598,8 +607,7 @@ export class UserManager {
logger.debug("storing user");
const storageString = user.toStorageString();
await this.settings.userStore.set(this._userStoreKey, storageString);
}
else {
} else {
this._logger.debug("removing user");
await this.settings.userStore.remove(this._userStoreKey);
}
Expand Down
16 changes: 15 additions & 1 deletion src/UserManagerEvents.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

import { UserManagerEvents } from "./UserManagerEvents";
import { UserManagerEvents, UserSessionErrorCallback } from "./UserManagerEvents";
import { UserManagerSettingsStore } from "./UserManagerSettings";

describe("UserManagerEvents", () => {
Expand Down Expand Up @@ -59,5 +59,19 @@ describe("UserManagerEvents", () => {
// assert
expect(e).toEqual(expected);
});

it("should pass error to callback", () => {
// arrange
const e: Error | null = null;
const cb: UserSessionErrorCallback = jest.fn();
const expected = new Error("boom");

// act
subject.addUserSessionError(cb);
subject._raiseUserSessionError();

// assert
expect(e).toEqual(expected);
});
});
});
24 changes: 24 additions & 0 deletions src/UserManagerEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export type UserSignedOutCallback = () => Promise<void> | void;
* @public
*/
export type UserSessionChangedCallback = () => Promise<void> | void;
/**
* @public
*/
export type UserSessionErrorCallback = () => Promise<void> | void;

/**
* @public
Expand All @@ -43,6 +47,7 @@ export class UserManagerEvents extends AccessTokenEvents {
private readonly _userSignedIn = new Event<[]>("User signed in");
private readonly _userSignedOut = new Event<[]>("User signed out");
private readonly _userSessionChanged = new Event<[]>("User session changed");
private readonly _userSessionError = new Event<[]>("User session error");

public constructor(settings: UserManagerSettingsStore) {
super({ expiringNotificationTimeInSeconds: settings.accessTokenExpiringNotificationTimeInSeconds });
Expand Down Expand Up @@ -163,4 +168,23 @@ export class UserManagerEvents extends AccessTokenEvents {
public _raiseUserSessionChanged(): void {
this._userSessionChanged.raise();
}
/**
* Add callback: Raised when the user session changed (when `monitorSession` is set).
* @see {@link UserManagerSettings.monitorSession}
*/
public addUserSessionError(cb: UserSessionErrorCallback): () => void {
return this._userSessionError.addHandler(cb);
}
/**
* Remove callback: Raised when the user session changed (when `monitorSession` is set).
*/
public removeUserSessionError(cb: UserSessionErrorCallback): void {
this._userSessionError.removeHandler(cb);
}
/**
* @internal
*/
public _raiseUserSessionError(): void {
this._userSessionError.raise();
}
}