Skip to content

Commit

Permalink
feat: #4 reduce any type of signin and signout chain
Browse files Browse the repository at this point in the history
  • Loading branch information
pamapa committed Aug 26, 2021
1 parent d591d92 commit cefd12a
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 49 deletions.
38 changes: 34 additions & 4 deletions src/OidcClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,39 @@ import { MetadataService } from "./MetadataService";
import { ErrorResponse } from "./ErrorResponse";
import { SigninRequest } from "./SigninRequest";
import { SigninResponse } from "./SigninResponse";
import { SignoutRequest } from "./SignoutRequest";
import { SignoutRequest, SignoutRequestArgs } from "./SignoutRequest";
import { SignoutResponse } from "./SignoutResponse";
import { SigninState } from "./SigninState";
import { State } from "./State";

export interface CreateSigninRequestArgs {
redirect_uri?: string;
response_type?: string;
scope?: string;

data?: any;
state?: any;

prompt?: string;
display?: string;
max_age?: number;
ui_locales?: string;
id_token_hint?: string;
login_hint?: string;
acr_values?: string;
resource?: string;
response_mode?: string;
request?: string;
request_uri?: string;
extraQueryParams?: Record<string, any>;
request_type?: string;
client_secret?: string;
extraTokenParams?: Record<string, any>;
skipUserInfo?: boolean;
}

export type CreateSignoutRequestArgs = Omit<SignoutRequestArgs, "url"> & { state?: any };

export class OidcClient {
public readonly settings: OidcClientSettingsStore;
public readonly metadataService: MetadataService;
Expand All @@ -30,9 +58,10 @@ export class OidcClient {
// data was meant to be the place a caller could indicate the data to
// have round tripped, but people were getting confused, so i added state (since that matches the spec)
// and so now if data is not passed, but state is then state will be used
// TODO: eliminate data in favor of state
data, state, prompt, display, max_age, ui_locales, id_token_hint, login_hint, acr_values,
resource, request, request_uri, response_mode, extraQueryParams, extraTokenParams, request_type, skipUserInfo
}: any = {}): Promise<SigninRequest> {
}: CreateSigninRequestArgs): Promise<SigninRequest> {
Log.debug("OidcClient.createSigninRequest");

response_type = response_type || this.settings.response_type;
Expand All @@ -59,12 +88,12 @@ export class OidcClient {

const signinRequest = new SigninRequest({
url,
authority: this.settings.authority,
client_id: this.settings.client_id,
redirect_uri,
response_type,
scope,
data: data || state,
authority: this.settings.authority,
prompt, display, max_age, ui_locales, id_token_hint, login_hint, acr_values,
resource, request, request_uri, extraQueryParams, extraTokenParams, request_type, response_mode,
client_secret: this.settings.client_secret,
Expand Down Expand Up @@ -112,8 +141,9 @@ export class OidcClient {
}

public async createSignoutRequest({
// TODO: eliminate data in favor of state
id_token_hint, data, state, post_logout_redirect_uri, extraQueryParams, request_type
}: any = {}) {
}: CreateSignoutRequestArgs = {}) {
Log.debug("OidcClient.createSignoutRequest");

post_logout_redirect_uri = post_logout_redirect_uri || this.settings.post_logout_redirect_uri;
Expand Down
33 changes: 31 additions & 2 deletions src/SigninRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@
import { Log, UrlUtility } from "./utils";
import { SigninState } from "./SigninState";

export interface SigninRequestArgs {
// mandatory
url: string;
authority: string;
client_id: string;
redirect_uri: string;
response_type: string;
scope: string;

// optional
data?: any;
prompt?: string;
display?: string;
max_age?: number;
ui_locales?: string;
id_token_hint?: string;
login_hint?: string;
acr_values?: string;
resource?: string;
response_mode?: string;
request?: string;
request_uri?: string;
extraQueryParams?: Record<string, any>;
request_type?: string;
client_secret?: string;
extraTokenParams?: Record<string, any>;
skipUserInfo?: boolean;
}

export class SigninRequest {
public readonly url: string;
public readonly state: SigninState;
Expand All @@ -14,7 +43,7 @@ export class SigninRequest {
// optional
data, prompt, display, max_age, ui_locales, id_token_hint, login_hint, acr_values, resource, response_mode,
request, request_uri, extraQueryParams, request_type, client_secret, extraTokenParams, skipUserInfo
}: any) {
}: SigninRequestArgs) {
if (!url) {
Log.error("SigninRequest.ctor: No url passed");
throw new Error("url");
Expand Down Expand Up @@ -72,7 +101,7 @@ export class SigninRequest {
url = UrlUtility.addQueryParam(url, "code_challenge_method", "S256");
}

const optional: any = { prompt, display, max_age, ui_locales, id_token_hint, login_hint, acr_values, resource, request, request_uri, response_mode };
const optional: Record<string, any> = { prompt, display, max_age, ui_locales, id_token_hint, login_hint, acr_values, resource, request, request_uri, response_mode };
for (const key in optional) {
if (optional[key]) {
url = UrlUtility.addQueryParam(url, key, optional[key]);
Expand Down
2 changes: 1 addition & 1 deletion src/SigninState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class SigninState extends State {
id?: string;
data?: any;
created?: number;
request_type: string;
request_type?: string;

nonce?: string | boolean;
code_verifier?: string | boolean;
Expand Down
17 changes: 15 additions & 2 deletions src/SignoutRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,26 @@
import { Log, UrlUtility } from "./utils";
import { State } from "./State";

export interface SignoutRequestArgs {
// mandatory
url: string;

// optional
id_token_hint?: string;
post_logout_redirect_uri?: string;
data?: string;
extraQueryParams?: Record<string, any>;
request_type?: string;
}

export class SignoutRequest {
public readonly url: string
public readonly state?: State

public constructor({
url, id_token_hint, post_logout_redirect_uri, data, extraQueryParams, request_type
}: any) {
url,
id_token_hint, post_logout_redirect_uri, data, extraQueryParams, request_type
}: SignoutRequestArgs) {
if (!url) {
Log.error("SignoutRequest.ctor: No url passed");
throw new Error("url");
Expand Down
4 changes: 2 additions & 2 deletions src/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ export class State {
public readonly id: string;
public readonly data: any;
public readonly created: number;
public readonly request_type: string;
public readonly request_type: string | undefined;

public constructor(args: {
id?: string;
data?: any;
created?: number;
request_type: string;
request_type?: string;
}) {
this.id = args.id || random();
this.data = args.data;
Expand Down
50 changes: 26 additions & 24 deletions src/UserManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { Log, JoseUtil, Timer } from "./utils";
import { INavigator, IFrameNavigator, PopupNavigator, RedirectNavigator } from "./navigators";
import { OidcClient } from "./OidcClient";
import { OidcClient, CreateSigninRequestArgs, CreateSignoutRequestArgs } from "./OidcClient";
import { UserManagerSettings, UserManagerSettingsStore } from "./UserManagerSettings";
import { User } from "./User";
import { UserManagerEvents } from "./UserManagerEvents";
Expand All @@ -15,19 +15,22 @@ import { TokenClient } from "./TokenClient";
import { SessionStatus } from "./SessionStatus";
import { SignoutResponse } from "./SignoutResponse";

type SigninArgs = CreateSigninRequestArgs & { current_sub?: string };
type SignoutArgs = CreateSignoutRequestArgs;

export class UserManager extends OidcClient {
declare public readonly settings: UserManagerSettingsStore; /* TODO: port-ts */

private readonly _redirectNavigator: RedirectNavigator;
private readonly _popupNavigator: PopupNavigator;
private readonly _iframeNavigator: IFrameNavigator;
private readonly _events: UserManagerEvents;
private readonly _silentRenewService: SilentRenewService;
protected readonly _redirectNavigator: RedirectNavigator;
protected readonly _popupNavigator: PopupNavigator;
protected readonly _iframeNavigator: IFrameNavigator;
protected readonly _events: UserManagerEvents;
protected readonly _silentRenewService: SilentRenewService;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
private readonly _sessionMonitor: SessionMonitor | null;
private readonly _tokenRevocationClient: TokenRevocationClient;
private readonly _tokenClient: TokenClient;
protected readonly _sessionMonitor: SessionMonitor | null;
protected readonly _tokenRevocationClient: TokenRevocationClient;
protected readonly _tokenClient: TokenClient;

public constructor(settings: UserManagerSettings) {
super(settings);
Expand Down Expand Up @@ -145,9 +148,9 @@ export class UserManager extends OidcClient {
return this._useRefreshToken(user);
}

const args: any = {
const args: SigninArgs = {
request_type: "si:s",
id_token_hint: this.settings.includeIdTokenInSilentRenew && user && user.id_token
id_token_hint: this.settings.includeIdTokenInSilentRenew && user ? user.id_token : undefined
};
if (user && this.settings.validateSubOnSilentRenew) {
Log.debug("UserManager.signinSilent, subject prior to silent renew: ", user.profile.sub);
Expand Down Expand Up @@ -213,7 +216,7 @@ export class UserManager extends OidcClient {
}
}

protected async _signinSilentIframe(args: any = {}) {
protected async _signinSilentIframe(args: SigninArgs) {
const url = args.redirect_uri || this.settings.silent_redirect_uri || this.settings.redirect_uri;
if (!url) {
Log.error("UserManager.signinSilent: No silent_redirect_uri configured");
Expand All @@ -225,7 +228,7 @@ export class UserManager extends OidcClient {

const user = await this._signin(args, this._iframeNavigator, {
startUrl: url,
silentRequestTimeout: args.silentRequestTimeout || this.settings.silentRequestTimeout
silentRequestTimeout: this.settings.silentRequestTimeout
});
if (user) {
if (user.profile && user.profile.sub) {
Expand Down Expand Up @@ -327,11 +330,11 @@ export class UserManager extends OidcClient {
}
}

protected async _signin(args: any, navigator: INavigator, navigatorParams: any = {}): Promise<User> {
protected async _signin(args: SigninArgs, navigator: INavigator, navigatorParams: any = {}): Promise<User> {
const navResponse = await this._signinStart(args, navigator, navigatorParams);
return this._signinEnd(navResponse.url, args);
}
protected async _signinStart(args: any, navigator: INavigator, navigatorParams: any = {}) {
protected async _signinStart(args: SigninArgs, navigator: INavigator, navigatorParams: any = {}) {
const handle = await navigator.prepare(navigatorParams);
Log.debug("UserManager._signinStart: got navigator window handle");

Expand All @@ -350,7 +353,7 @@ export class UserManager extends OidcClient {
throw err;
}
}
protected async _signinEnd(url: string, args: any = {}): Promise<User> {
protected async _signinEnd(url: string, args: SigninArgs = {}): Promise<User> {
const signinResponse = await this.processSigninResponse(url);
Log.debug("UserManager._signinEnd: got signin response");

Expand Down Expand Up @@ -379,7 +382,7 @@ export class UserManager extends OidcClient {
}

public async signoutRedirect(): Promise<void> {
const args: any = {
const args: SignoutArgs = {
request_type: "so:r"
};
const postLogoutRedirectUri = this.settings.post_logout_redirect_uri;
Expand All @@ -398,10 +401,9 @@ export class UserManager extends OidcClient {

public async signoutPopup(): Promise<void> {
const url = this.settings.popup_post_logout_redirect_uri || this.settings.post_logout_redirect_uri;
const args: any = {
const args: SignoutArgs = {
request_type: "so:p",
post_logout_redirect_uri: url,
display: "popup",
post_logout_redirect_uri: url
};
if (args.post_logout_redirect_uri) {
// we're putting a dummy entry in here because we
Expand All @@ -414,8 +416,8 @@ export class UserManager extends OidcClient {

await this._signout(args, this._popupNavigator, {
startUrl: url,
popupWindowFeatures: args.popupWindowFeatures || this.settings.popupWindowFeatures,
popupWindowTarget: args.popupWindowTarget || this.settings.popupWindowTarget
popupWindowFeatures: this.settings.popupWindowFeatures,
popupWindowTarget: this.settings.popupWindowTarget
});
Log.info("UserManager.signoutPopup: successful");
}
Expand All @@ -430,11 +432,11 @@ export class UserManager extends OidcClient {
Log.info("UserManager.signoutPopupCallback: successful");
}

protected async _signout(args: any, navigator: INavigator, navigatorParams: any = {}) {
protected async _signout(args: SignoutArgs, navigator: INavigator, navigatorParams: any = {}) {
const navResponse = await this._signoutStart(args, navigator, navigatorParams);
return this._signoutEnd(navResponse.url);
}
protected async _signoutStart(args: any = {}, navigator: INavigator, navigatorParams: any = {}) {
protected async _signoutStart(args: SignoutArgs = {}, navigator: INavigator, navigatorParams: any = {}) {
const handle = await navigator.prepare(navigatorParams);
Log.debug("UserManager._signoutStart: got navigator window handle");

Expand Down
Loading

0 comments on commit cefd12a

Please sign in to comment.