UNPKG

@okta-dfuhriman/okta-auth-js

Version:
176 lines (152 loc) 6.67 kB
/* eslint-disable complexity */ /*! * Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved. * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (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 { DEFAULT_MAX_CLOCK_SKEW } from '../../constants'; import { removeTrailingSlash, toAbsoluteUrl } from '../../util/url'; import { isBrowser } from '../../features'; import { createHttpOptionsConstructor } from '../../http/options'; import { OAuthResponseMode, OAuthResponseType, OAuthAuthorizationDetail, OktaAuthOAuthInterface, OktaAuthOAuthOptions, SetLocationFunction, TokenManagerOptions, TransactionManagerOptions } from '../types'; import { enableSharedStorage } from './node'; import AuthSdkError from '../../errors/AuthSdkError'; function assertValidConfig(args) { args = args || {}; var scopes = args.scopes; if (scopes && !Array.isArray(scopes)) { throw new AuthSdkError('scopes must be a array of strings. ' + 'Required usage: new OktaAuth({scopes: ["openid", "email"]})'); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var issuer = args.issuer!; if (!issuer) { throw new AuthSdkError('No issuer passed to constructor. ' + 'Required usage: new OktaAuth({issuer: "https://{yourOktaDomain}.com/oauth2/{authServerId}"})'); } var isUrlRegex = new RegExp('^http?s?://.+'); if (!isUrlRegex.test(issuer)) { throw new AuthSdkError('Issuer must be a valid URL. ' + 'Required usage: new OktaAuth({issuer: "https://{yourOktaDomain}.com/oauth2/{authServerId}"})'); } if (issuer.indexOf('-admin.') !== -1) { throw new AuthSdkError('Issuer URL passed to constructor contains "-admin" in subdomain. ' + 'Required usage: new OktaAuth({issuer: "https://{yourOktaDomain}.com})'); } } export function createOAuthOptionsConstructor() { const HttpOptionsConstructor = createHttpOptionsConstructor(); return class OAuthOptionsConstructor extends HttpOptionsConstructor implements Required<OktaAuthOAuthOptions> { // CustomUrls issuer: string; authorizeUrl: string; userinfoUrl: string; tokenUrl: string; revokeUrl: string; logoutUrl: string; // TokenParams pkce: boolean; clientId: string; redirectUri: string; responseType: OAuthResponseType | OAuthResponseType[]; responseMode: OAuthResponseMode; state: string; scopes: string[]; ignoreSignature: boolean; codeChallenge: string; codeChallengeMethod: string; acrValues: string; maxAge: string | number; audience: string | string[]; // Additional options tokenManager: TokenManagerOptions; postLogoutRedirectUri: string; restoreOriginalUri: (oktaAuth: OktaAuthOAuthInterface, originalUri?: string) => Promise<void>; transactionManager: TransactionManagerOptions; provider: 'okta-wic' | 'okta-cic'; // For PAR only! pushAuthorizationUrl: string; authorizationDetails: OAuthAuthorizationDetail[]; jwtAuthorizationRequest: boolean; pushAuthorizationRequest: boolean; // For server-side web applications ONLY! clientSecret: string; setLocation: SetLocationFunction; // Workaround for bad client time/clock ignoreLifetime: boolean; maxClockSkew: number; // eslint-disable-next-line max-statements constructor(options: any) { super(options); assertValidConfig(options); this.issuer = removeTrailingSlash(options.issuer); this.tokenUrl = removeTrailingSlash(options.tokenUrl); this.authorizeUrl = removeTrailingSlash(options.authorizeUrl); this.userinfoUrl = removeTrailingSlash(options.userinfoUrl); this.revokeUrl = removeTrailingSlash(options.revokeUrl); this.logoutUrl = removeTrailingSlash(options.logoutUrl); this.pushAuthorizationUrl = removeTrailingSlash(options?.pushAuthorizationUrl); this.authorizationDetails = options?.authorizationDetails; this.pkce = options.pkce === false ? false : true; // PKCE defaults to true this.clientId = options.clientId; this.redirectUri = options.redirectUri; if (isBrowser()) { this.redirectUri = toAbsoluteUrl(options.redirectUri, window.location.origin); // allow relative URIs } this.responseType = options.responseType; this.responseMode = options.responseMode; this.state = options.state; this.scopes = options.scopes; // Give the developer the ability to disable token signature validation. this.ignoreSignature = !!options.ignoreSignature; this.codeChallenge = options.codeChallenge; this.codeChallengeMethod = options.codeChallengeMethod; this.acrValues = options.acrValues; this.maxAge = options.maxAge; this.audience = options.audience; this.tokenManager = options.tokenManager; this.postLogoutRedirectUri = options.postLogoutRedirectUri; this.restoreOriginalUri = options.restoreOriginalUri; this.transactionManager = { enableSharedStorage, ...options.transactionManager }; this.jwtAuthorizationRequest = options?.jwtAuthorizationRequest ?? false; this.pushAuthorizationRequest = options?.pushAuthorizationRequest ?? false; this.clientSecret = options.clientSecret; this.setLocation = options.setLocation; this.provider = options?.provider ?? 'okta-wic'; // As some end user's devices can have their date // and time incorrectly set, allow for the disabling // of the jwt liftetime validation this.ignoreLifetime = !!options.ignoreLifetime; // Digital clocks will drift over time, so the server // can misalign with the time reported by the browser. // The maxClockSkew allows relaxing the time-based // validation of tokens (in seconds, not milliseconds). // It currently defaults to 300, because 5 min is the // default maximum tolerance allowed by Kerberos. // (https://technet.microsoft.com/en-us/library/cc976357.aspx) if (!options.maxClockSkew && options.maxClockSkew !== 0) { this.maxClockSkew = DEFAULT_MAX_CLOCK_SKEW; } else { this.maxClockSkew = options.maxClockSkew; } } }; }