UNPKG

@asgardeo/auth-js

Version:

Asgardeo Auth JS SDK to be used in JavaScript and TypeScript applications.

675 lines (632 loc) 22.3 kB
/** * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import { OIDC_SCOPE, OP_CONFIG_INITIATED, ResponseMode, SIGN_OUT_SUCCESS_PARAM, STATE } from "./constants"; import { AuthenticationCore } from "./core"; import { DataLayer } from "./data"; import { CryptoHelper } from "./helpers"; import { AuthClientConfig, BasicUserInfo, CryptoUtils, CustomGrantConfig, DecodedIDTokenPayload, FetchResponse, GetAuthURLConfig, OIDCEndpoints, Store, TokenResponse } from "./models"; /** * Default configurations. */ const DefaultConfig: Partial<AuthClientConfig<unknown>> = { clockTolerance: 300, enablePKCE: true, responseMode: ResponseMode.query, scope: [ OIDC_SCOPE ], sendCookiesInRequests: true, validateIDToken: true, validateIDTokenIssuer: true }; /** * This class provides the necessary methods needed to implement authentication. */ export class AsgardeoAuthClient<T> { private _dataLayer!: DataLayer<T>; private _authenticationCore!: AuthenticationCore<T>; private static _instanceID: number; static _authenticationCore: any; /** * This is the constructor method that returns an instance of the . * * @param store - The store object. * * @example * ``` * const _store: Store = new DataStore(); * const auth = new AsgardeoAuthClient<CustomClientConfig>(_store); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#constructor} * * @preserve */ public constructor() {} /** * * This method initializes the SDK with the config data. * * @param config - The config object to initialize with. * * @example * const config = \{ * signInRedirectURL: "http://localhost:3000/sign-in", * clientID: "client ID", * baseUrl: "https://localhost:9443" * \} * * await auth.initialize(config); * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#initialize} * * @preserve */ public async initialize( config: AuthClientConfig<T>, store: Store, cryptoUtils: CryptoUtils, instanceID?: number ): Promise<void> { const clientId: string = config.clientID; if (!AsgardeoAuthClient._instanceID) { AsgardeoAuthClient._instanceID = 0; } else { AsgardeoAuthClient._instanceID += 1; } if (instanceID) { AsgardeoAuthClient._instanceID = instanceID; } if (!clientId) { this._dataLayer = new DataLayer<T>(`instance_${ AsgardeoAuthClient._instanceID }`, store); } else { this._dataLayer = new DataLayer<T>(`instance_${ AsgardeoAuthClient._instanceID }-${ clientId }`, store); } this._authenticationCore = new AuthenticationCore(this._dataLayer, cryptoUtils); AsgardeoAuthClient._authenticationCore = new AuthenticationCore(this._dataLayer, cryptoUtils); await this._dataLayer.setConfigData({ ...DefaultConfig, ...config, scope: [ ...(DefaultConfig.scope ?? []), ...(config.scope?.filter((scope: string) => !DefaultConfig?.scope?.includes(scope)) ?? []) ] }); } /** * This method returns the `DataLayer` object that allows you to access authentication data. * * @returns - The `DataLayer` object. * * @example * ``` * const data = auth.getDataLayer(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getDataLayer} * * @preserve */ public getDataLayer(): DataLayer<T> { return this._dataLayer; } /** * This method returns the `instanceID` variable of the given instance. * * @returns - The `instanceID` number. * * @example * ``` * const instanceId = auth.getInstanceID(); * ``` * * @preserve */ public getInstanceID(): number { return AsgardeoAuthClient._instanceID; } /** * This is an async method that returns a Promise that resolves with the authorization URL parameters. * * @param config - (Optional) A config object to force initialization and pass * custom path parameters such as the `fidp` parameter. * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A promise that resolves with the authorization URL parameters. * * @example * ``` * auth.getAuthorizationURLParams().then((params)=>{ * // console.log(params); * }).catch((error)=>{ * // console.error(error); * }); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getAuthorizationURLParams} * * @preserve */ public async getAuthorizationURLParams( config?: GetAuthURLConfig, userID?: string ): Promise<Map<string, string>> { const authRequestConfig: GetAuthURLConfig = { ...config }; delete authRequestConfig?.forceInit; if (await this._dataLayer.getTemporaryDataParameter(OP_CONFIG_INITIATED)) { return this._authenticationCore.getAuthorizationURLParams( authRequestConfig, userID ); } return this._authenticationCore .getOIDCProviderMetaData(config?.forceInit as boolean) .then(() => { return this._authenticationCore.getAuthorizationURLParams( authRequestConfig, userID ); }); } /** * This is an async method that returns a Promise that resolves with the authorization URL. * * @param config - (Optional) A config object to force initialization and pass * custom path parameters such as the fidp parameter. * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A promise that resolves with the authorization URL. * * @example * ``` * auth.getAuthorizationURL().then((url)=>{ * // console.log(url); * }).catch((error)=>{ * // console.error(error); * }); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getAuthorizationURL} * * @preserve */ public async getAuthorizationURL(config?: GetAuthURLConfig, userID?: string): Promise<string> { const authRequestConfig: GetAuthURLConfig = { ...config }; delete authRequestConfig?.forceInit; if (await this._dataLayer.getTemporaryDataParameter(OP_CONFIG_INITIATED)) { return this._authenticationCore.getAuthorizationURL(authRequestConfig, userID); } return this._authenticationCore.getOIDCProviderMetaData(config?.forceInit as boolean).then(() => { return this._authenticationCore.getAuthorizationURL(authRequestConfig, userID); }); } /** * This is an async method that sends a request to obtain the access token and returns a Promise * that resolves with the token and other relevant data. * * @param authorizationCode - The authorization code. * @param sessionState - The session state. * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with the token response. * * @example * ``` * auth.requestAccessToken(authCode, sessionState).then((token)=>{ * // console.log(token); * }).catch((error)=>{ * // console.error(error); * }); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#requestAccessToken} * * * @preserve */ public async requestAccessToken( authorizationCode: string, sessionState: string, state: string, userID?: string, tokenRequestConfig?: { params: Record<string, unknown> } ): Promise<TokenResponse> { if (await this._dataLayer.getTemporaryDataParameter(OP_CONFIG_INITIATED)) { return this._authenticationCore.requestAccessToken(authorizationCode, sessionState, state, userID, tokenRequestConfig); } return this._authenticationCore.getOIDCProviderMetaData(false).then(() => { return this._authenticationCore.requestAccessToken(authorizationCode, sessionState, state, userID, tokenRequestConfig); }); } /** * This method returns the sign-out URL. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * **This doesn't clear the authentication data.** * * @returns - A Promise that resolves with the sign-out URL. * * @example * ``` * const signOutUrl = await auth.getSignOutURL(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getSignOutURL} * * @preserve */ public async getSignOutURL(userID?: string): Promise<string> { return this._authenticationCore.getSignOutURL(userID); } /** * This method returns OIDC service endpoints that are fetched from the `.well-known` endpoint. * * @returns - A Promise that resolves with an object containing the OIDC service endpoints. * * @example * ``` * const endpoints = await auth.getOIDCServiceEndpoints(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getOIDCServiceEndpoints} * * @preserve */ public async getOIDCServiceEndpoints(): Promise<OIDCEndpoints> { return this._authenticationCore.getOIDCServiceEndpoints(); } /** * This method decodes the payload of the ID token and returns it. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with the decoded ID token payload. * * @example * ``` * const decodedIdToken = await auth.getDecodedIDToken(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getDecodedIDToken} * * @preserve */ public async getDecodedIDToken(userID?: string): Promise<DecodedIDTokenPayload> { return this._authenticationCore.getDecodedIDToken(userID); } /** * This method returns the ID token. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with the ID token. * * @example * ``` * const idToken = await auth.getIDToken(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getIDToken} * * @preserve */ public async getIDToken(userID?: string): Promise<string> { return this._authenticationCore.getIDToken(userID); } /** * This method returns the basic user information obtained from the ID token. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with an object containing the basic user information. * * @example * ``` * const userInfo = await auth.getBasicUserInfo(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getBasicUserInfo} * * @preserve */ public async getBasicUserInfo(userID?: string): Promise<BasicUserInfo> { return this._authenticationCore.getBasicUserInfo(userID); } /** * This method returns the crypto helper object. * * @returns - A Promise that resolves with a CryptoHelper object. * * @example * ``` * const cryptoHelper = await auth.CryptoHelper(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getCryptoHelper} * * @preserve */ public async getCryptoHelper(): Promise<CryptoHelper> { return this._authenticationCore.getCryptoHelper(); } /** * This method revokes the access token. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * **This method also clears the authentication data.** * * @returns - A Promise that returns the response of the revoke-access-token request. * * @example * ``` * auth.revokeAccessToken().then((response)=>{ * // console.log(response); * }).catch((error)=>{ * // console.error(error); * }); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#revokeAccessToken} * * @preserve */ public revokeAccessToken(userID?: string): Promise<FetchResponse> { return this._authenticationCore.revokeAccessToken(userID); } /** * This method refreshes the access token and returns a Promise that resolves with the new access * token and other relevant data. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with the token response. * * @example * ``` * auth.refreshAccessToken().then((response)=>{ * // console.log(response); * }).catch((error)=>{ * // console.error(error); * }); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#refreshAccessToken} * * @preserve */ public refreshAccessToken(userID?: string): Promise<TokenResponse> { return this._authenticationCore.refreshAccessToken(userID); } /** * This method returns the access token. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with the access token. * * @example * ``` * const accessToken = await auth.getAccessToken(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getAccessToken} * * @preserve */ public async getAccessToken(userID?: string): Promise<string> { return this._authenticationCore.getAccessToken(userID); } /** * This method sends a custom-grant request and returns a Promise that resolves with the response * depending on the config passed. * * @param config - A config object containing the custom grant configurations. * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with the response depending * on your configurations. * * @example * ``` * const config = { * attachToken: false, * data: { * client_id: "{{clientID}}", * grant_type: "account_switch", * scope: "{{scope}}", * token: "{{token}}", * }, * id: "account-switch", * returnResponse: true, * returnsSession: true, * signInRequired: true * } * * auth.requestCustomGrant(config).then((response)=>{ * // console.log(response); * }).catch((error)=>{ * // console.error(error); * }); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#requestCustomGrant} * * @preserve */ public requestCustomGrant(config: CustomGrantConfig, userID?: string): Promise<TokenResponse | FetchResponse> { return this._authenticationCore.requestCustomGrant(config, userID); } /** * This method returns if the user is authenticated or not. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @returns - A Promise that resolves with `true` if the user is authenticated, `false` otherwise. * * @example * ``` * await auth.isAuthenticated(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isAuthenticated} * * @preserve */ public async isAuthenticated(userID?: string): Promise<boolean> { return this._authenticationCore.isAuthenticated(userID); } /** * This method returns the PKCE code generated during the generation of the authentication URL. * * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * @param state - The state parameter that was passed in the authentication URL. * * @returns - A Promise that resolves with the PKCE code. * * @example * ``` * const pkce = await getPKCECode(); * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getPKCECode} * * @preserve */ public async getPKCECode(state: string, userID?: string): Promise<string> { return this._authenticationCore.getPKCECode(state, userID); } /** * This method sets the PKCE code to the data store. * * @param pkce - The PKCE code. * @param state - The state parameter that was passed in the authentication URL. * @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user * scenarios where each user should be uniquely identified. * * @example * ``` * await auth.setPKCECode("pkce_code") * ``` * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#setPKCECode} * * @preserve */ public async setPKCECode(pkce: string, state: string, userID?: string): Promise<void> { await this._authenticationCore.setPKCECode(pkce, state, userID); } /** * This method returns if the sign-out is successful or not. * * @param signOutRedirectUrl - The URL to which the user has been redirected to after signing-out. * * **The server appends path parameters to the `signOutRedirectURL` and these path parameters * are required for this method to function.** * * @returns - `true` if successful, `false` otherwise. * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isSignOutSuccessful} * * @preserve */ public static isSignOutSuccessful(signOutRedirectURL: string): boolean { const url: URL = new URL(signOutRedirectURL); const stateParam: string | null = url.searchParams.get(STATE); const error: boolean = Boolean(url.searchParams.get("error")); return stateParam ? stateParam === SIGN_OUT_SUCCESS_PARAM && !error : false; } /** * This method returns if the sign-out has failed or not. * * @param signOutRedirectUrl - The URL to which the user has been redirected to after signing-out. * * **The server appends path parameters to the `signOutRedirectURL` and these path parameters * are required for this method to function.** * * @returns - `true` if successful, `false` otherwise. * * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#didSignOutFail} * * @preserve */ public static didSignOutFail(signOutRedirectURL: string): boolean { const url: URL = new URL(signOutRedirectURL); const stateParam: string | null = url.searchParams.get(STATE); const error: boolean = Boolean(url.searchParams.get("error")); return stateParam ? stateParam === SIGN_OUT_SUCCESS_PARAM && error : false; } /** * This method updates the configuration that was passed into the constructor when instantiating this class. * * @param config - A config object to update the SDK configurations with. * * @example * ``` * const config = { * signInRedirectURL: "http://localhost:3000/sign-in", * clientID: "client ID", * baseUrl: "https://localhost:9443" * } * * await auth.updateConfig(config); * ``` * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#updateConfig} * * @preserve */ public async updateConfig(config: Partial<AuthClientConfig<T>>): Promise<void> { await this._authenticationCore.updateConfig(config); } public static async clearUserSessionData(userID?: string): Promise<void> { await this._authenticationCore.clearUserSessionData(userID); } }