From e4c5ccaedbc2d49b5ca56791dffe0a698547b19c Mon Sep 17 00:00:00 2001 From: Aaron Granick Date: Thu, 14 Apr 2022 18:59:06 +0000 Subject: [PATCH] removes support for legacy PKCE / oauth storage OKTA-362589 <<>> Artifact: okta-auth-js Files changed count: 17 PR Link: "https://github.com/okta/okta-auth-js/pull/1181" --- CHANGELOG.md | 7 + lib/OktaAuth.ts | 6 - lib/StorageManager.ts | 21 +- lib/TransactionManager.ts | 183 ----------- lib/browser/browserStorage.ts | 11 - lib/constants.ts | 3 - lib/oidc/getWithRedirect.ts | 2 +- lib/oidc/parseFromUrl.ts | 8 +- lib/server/serverStorage.ts | 5 - lib/types/Storage.ts | 22 -- lib/types/Transaction.ts | 3 - test/spec/TransactionManager.ts | 407 ++---------------------- test/spec/oidc/getWithRedirect.ts | 4 +- test/spec/oidc/getWithRedirectLegacy.ts | 399 ++--------------------- test/spec/oidc/parseFromUrl.ts | 150 ++++----- test/spec/oidc/util/oauth.ts | 3 - test/support/oauthUtil.js | 15 +- 17 files changed, 122 insertions(+), 1127 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d74b6564..39d531007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 7.0.0 + +### Breaking Changes + +- [#1181](https://github.com/okta/okta-auth-js/pull/1181) - Removes legacy PKCE/OAuth storage + + ## 6.8.0 ### Other diff --git a/lib/OktaAuth.ts b/lib/OktaAuth.ts index 0a6dca7fb..5ea9890e7 100644 --- a/lib/OktaAuth.ts +++ b/lib/OktaAuth.ts @@ -200,12 +200,6 @@ class OktaAuth implements OktaAuthInterface, SigninAPI, SignoutAPI { computeChallenge: PKCE.computeChallenge }; - // Add shims for compatibility, these will be removed in next major version. OKTA-362589 - Object.assign(this.options.storageUtil || {}, { - getPKCEStorage: this.storageManager.getLegacyPKCEStorage.bind(this.storageManager), - getHttpCache: this.storageManager.getHttpCache.bind(this.storageManager), - }); - this._pending = { handleLogin: false }; if (isBrowser()) { diff --git a/lib/StorageManager.ts b/lib/StorageManager.ts index 480ad44c4..7df562443 100644 --- a/lib/StorageManager.ts +++ b/lib/StorageManager.ts @@ -13,20 +13,17 @@ import { - PKCE_STORAGE_NAME, TOKEN_STORAGE_NAME, TRANSACTION_STORAGE_NAME, SHARED_TRANSACTION_STORAGE_NAME, ORIGINAL_URI_STORAGE_NAME, IDX_RESPONSE_STORAGE_NAME, CACHE_STORAGE_NAME, - REDIRECT_OAUTH_PARAMS_NAME } from './constants'; import { StorageUtil, StorageProvider, StorageOptions, - PKCEStorage, CookieOptions, TransactionStorage, IdxResponseStorage, @@ -76,7 +73,9 @@ export class StorageManager { options.sessionCookie = true; } - // Maintain compatibility. Automatically fallback. May change in next major version. OKTA-362589 + // If both storageType and storageTypes are specified, then storageType will be used first + // If storageType cannot be used but it matches an entry in storageTypes, subsequent entries may be used as fallback + // if storageType does not match an entry in storageTypes then storageType is used with no fallback. if (storageType && storageTypes) { const idx = storageTypes.indexOf(storageType); if (idx >= 0) { @@ -187,18 +186,4 @@ export class StorageManager { return new SavedObject(storage, storageKey); } - // Will be removed in an upcoming major version. OKTA-362589 - getLegacyPKCEStorage(options?: StorageOptions): PKCEStorage { - options = this.getOptionsForSection('legacy-pkce', options); - const storage = this.getStorage(options); - const storageKey = options.storageKey || PKCE_STORAGE_NAME; - return new SavedObject(storage, storageKey); - } - - getLegacyOAuthParamsStorage(options?: StorageOptions): StorageProvider { - options = this.getOptionsForSection('legacy-oauth-params', options); - const storage = this.getStorage(options); - const storageKey = options.storageKey || REDIRECT_OAUTH_PARAMS_NAME; - return new SavedObject(storage, storageKey); - } } diff --git a/lib/TransactionManager.ts b/lib/TransactionManager.ts index 16a9bafd5..a52ab1b1a 100644 --- a/lib/TransactionManager.ts +++ b/lib/TransactionManager.ts @@ -11,19 +11,13 @@ */ -import { AuthSdkError } from './errors'; -import { REDIRECT_NONCE_COOKIE_NAME, REDIRECT_OAUTH_PARAMS_NAME, REDIRECT_STATE_COOKIE_NAME } from './constants'; import { StorageManager } from './StorageManager'; import { StorageProvider, TransactionMeta, isTransactionMeta, - isOAuthTransactionMeta, - PKCETransactionMeta, - OAuthTransactionMeta, TransactionMetaOptions, TransactionManagerOptions, - CookieStorage, SavedIdxResponse, IntrospectOptions } from './types'; @@ -43,20 +37,12 @@ export interface ClearTransactionMetaOptions extends TransactionMetaOptions { export default class TransactionManager { options: TransactionManagerOptions; storageManager: StorageManager; - legacyWidgetSupport: boolean; - saveNonceCookie: boolean; - saveStateCookie: boolean; - saveParamsCookie: boolean; enableSharedStorage: boolean; saveLastResponse: boolean; constructor(options: TransactionManagerOptions) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.storageManager = options.storageManager!; - this.legacyWidgetSupport = options.legacyWidgetSupport === false ? false : true; - this.saveNonceCookie = options.saveNonceCookie === false ? false : true; - this.saveStateCookie = options.saveStateCookie === false ? false : true; - this.saveParamsCookie = options.saveParamsCookie === false ? false : true; this.enableSharedStorage = options.enableSharedStorage === false ? false : true; this.saveLastResponse = options.saveLastResponse === false ? false : true; this.options = options; @@ -81,19 +67,6 @@ export default class TransactionManager { if (options.clearIdxResponse !== false) { this.clearIdxResponse(); } - - if (!this.legacyWidgetSupport) { - return; - } - - // This is for compatibility with older versions of the signin widget. OKTA-304806 - if (options.oauth) { - this.clearLegacyOAuthParams(); - } - - if (options.pkce) { - this.clearLegacyPKCE(); - } } // eslint-disable-next-line complexity @@ -118,47 +91,6 @@ export default class TransactionManager { if (this.enableSharedStorage && meta.state) { saveTransactionToSharedStorage(this.storageManager, meta.state, meta); } - - if (!options.oauth) { - return; - } - - // Legacy cookie storage - if (this.saveNonceCookie || this.saveStateCookie || this.saveParamsCookie) { - const cookieStorage: CookieStorage = this.storageManager.getStorage({ storageType: 'cookie' }) as CookieStorage; - - if (this.saveParamsCookie) { - const { - responseType, - state, - nonce, - scopes, - clientId, - urls, - ignoreSignature - } = meta; - const oauthParams = { - responseType, - state, - nonce, - scopes, - clientId, - urls, - ignoreSignature - }; - cookieStorage.setItem(REDIRECT_OAUTH_PARAMS_NAME, JSON.stringify(oauthParams), null); - } - - if (this.saveNonceCookie && meta.nonce) { - // Set nonce cookie for servers to validate nonce in id_token - cookieStorage.setItem(REDIRECT_NONCE_COOKIE_NAME, meta.nonce, null); - } - - if (this.saveStateCookie && meta.state) { - // Set state cookie for servers to validate state - cookieStorage.setItem(REDIRECT_STATE_COOKIE_NAME, meta.state, null); - } - } } exists(options: TransactionMetaOptions = {}): boolean { @@ -192,124 +124,9 @@ export default class TransactionManager { return meta; } - if (!this.legacyWidgetSupport) { - return null; - } - - // This is for compatibility with older versions of the signin widget. OKTA-304806 - if (options.oauth) { - try { - const oauthParams = this.loadLegacyOAuthParams(); - Object.assign(meta, oauthParams); - } finally { - this.clearLegacyOAuthParams(); - } - } - - if (options.pkce) { - try { - const pkceMeta: PKCETransactionMeta = this.loadLegacyPKCE(); - Object.assign(meta, pkceMeta); - } finally { - this.clearLegacyPKCE(); - } - } - - if (isTransactionMeta(meta)) { - return meta; - } return null; } - // This is for compatibility with older versions of the signin widget. OKTA-304806 - clearLegacyPKCE(): void { - // clear storages - let storage: StorageProvider; - - if (this.storageManager.storageUtil.testStorageType('localStorage')) { - storage = this.storageManager.getLegacyPKCEStorage({ storageType: 'localStorage' }); - storage.clearStorage(); - } - - if (this.storageManager.storageUtil.testStorageType('sessionStorage')) { - storage = this.storageManager.getLegacyPKCEStorage({ storageType: 'sessionStorage' }); - storage.clearStorage(); - } - } - - loadLegacyPKCE(): PKCETransactionMeta { - let storage: StorageProvider; - let obj; - - // Try reading from localStorage first. - if (this.storageManager.storageUtil.testStorageType('localStorage')) { - storage = this.storageManager.getLegacyPKCEStorage({ storageType: 'localStorage' }); - obj = storage.getStorage(); - if (obj && obj.codeVerifier) { - return obj; - } - } - - // If meta is not valid, read from sessionStorage. This is expected for more recent versions of the widget. - if (this.storageManager.storageUtil.testStorageType('sessionStorage')) { - storage = this.storageManager.getLegacyPKCEStorage({ storageType: 'sessionStorage' }); - obj = storage.getStorage(); - if (obj && obj.codeVerifier) { - return obj; - } - } - - // If meta is not valid, throw an exception to avoid misleading server-side error - // The most likely cause of this error is trying to handle a callback twice - // eslint-disable-next-line max-len - throw new AuthSdkError('Could not load PKCE codeVerifier from storage. This may indicate the auth flow has already completed or multiple auth flows are executing concurrently.', undefined); - } - - clearLegacyOAuthParams(): void { - // clear storages - let storage: StorageProvider; - - if (this.storageManager.storageUtil.testStorageType('sessionStorage')) { - storage = this.storageManager.getLegacyOAuthParamsStorage({ storageType: 'sessionStorage' }); - storage.clearStorage(); - } - - if (this.storageManager.storageUtil.testStorageType('cookie')) { - storage = this.storageManager.getLegacyOAuthParamsStorage({ storageType: 'cookie' }); - storage.clearStorage(); - } - } - - loadLegacyOAuthParams(): OAuthTransactionMeta { - let storage: StorageProvider; - let oauthParams; - - // load first from session storage - if (this.storageManager.storageUtil.testStorageType('sessionStorage')) { - storage = this.storageManager.getLegacyOAuthParamsStorage({ storageType: 'sessionStorage' }); - oauthParams = storage.getStorage(); - } - if (isOAuthTransactionMeta(oauthParams)) { - return oauthParams; - } - - // try to load from cookie - if (this.storageManager.storageUtil.testStorageType('cookie')) { - storage = this.storageManager.getLegacyOAuthParamsStorage({ storageType: 'cookie' }); - oauthParams = storage.getStorage(); - } - - if (isOAuthTransactionMeta(oauthParams)) { - return oauthParams; - } - - - throw new AuthSdkError('Unable to retrieve OAuth redirect params from storage'); - - // Something is there but we don't recognize it - // throw new AuthSdkError('Unable to parse the ' + REDIRECT_OAUTH_PARAMS_NAME + ' value from storage'); - } - saveIdxResponse(data: SavedIdxResponse): void { if (!this.saveLastResponse) { return; diff --git a/lib/browser/browserStorage.ts b/lib/browser/browserStorage.ts index a46478fd7..7c7fcdf4f 100644 --- a/lib/browser/browserStorage.ts +++ b/lib/browser/browserStorage.ts @@ -15,9 +15,7 @@ import Cookies from 'js-cookie'; import AuthSdkError from '../errors/AuthSdkError'; import { - StorageProvider, StorageOptions, - PKCEStorage, CookieOptions, SimpleStorage, StorageType, @@ -30,15 +28,6 @@ import { isIE11OrLess } from '../features'; // Building this as an object allows us to mock the functions in our tests var storageUtil: BrowserStorageUtil = { - // These are shimmed in `OktaAuthBase.ts` - getHttpCache(): StorageProvider { - return null as never as StorageProvider; - }, - - getPKCEStorage(): PKCEStorage { - return null as never as PKCEStorage; - }, - // IE11 bug that Microsoft doesn't plan to fix // https://connect.microsoft.com/IE/Feedback/Details/1496040 browserHasLocalStorage: function() { diff --git a/lib/constants.ts b/lib/constants.ts index cf1483998..abcf80db4 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -14,9 +14,6 @@ export const STATE_TOKEN_KEY_NAME = 'oktaStateToken'; export const DEFAULT_POLLING_DELAY = 500; export const DEFAULT_MAX_CLOCK_SKEW = 300; export const DEFAULT_CACHE_DURATION = 86400; -export const REDIRECT_OAUTH_PARAMS_NAME = 'okta-oauth-redirect-params'; -export const REDIRECT_STATE_COOKIE_NAME = 'okta-oauth-state'; -export const REDIRECT_NONCE_COOKIE_NAME = 'okta-oauth-nonce'; export const TOKEN_STORAGE_NAME = 'okta-token-storage'; export const CACHE_STORAGE_NAME = 'okta-cache-storage'; export const PKCE_STORAGE_NAME = 'okta-pkce-storage'; diff --git a/lib/oidc/getWithRedirect.ts b/lib/oidc/getWithRedirect.ts index d71f2cd59..074624098 100644 --- a/lib/oidc/getWithRedirect.ts +++ b/lib/oidc/getWithRedirect.ts @@ -27,6 +27,6 @@ export async function getWithRedirect(sdk: OktaAuthOIDCInterface, options?: Toke const tokenParams = await prepareTokenParams(sdk, options); const meta = createOAuthMeta(sdk, tokenParams); const requestUrl = meta.urls.authorizeUrl + buildAuthorizeParams(tokenParams); - sdk.transactionManager.save(meta, { oauth: true }); + sdk.transactionManager.save(meta); sdk.token.getWithRedirect._setLocation(requestUrl); } diff --git a/lib/oidc/parseFromUrl.ts b/lib/oidc/parseFromUrl.ts index 7b1832f3c..899181f26 100644 --- a/lib/oidc/parseFromUrl.ts +++ b/lib/oidc/parseFromUrl.ts @@ -95,12 +95,14 @@ export async function parseFromUrl(sdk, options?: string | ParseFromUrlOptions): const res: OAuthResponse = parseOAuthResponseFromUrl(sdk, options); const state = res.state; const oauthParams: TransactionMeta = sdk.transactionManager.load({ - oauth: true, - pkce: sdk.options.pkce, state }); if (!oauthParams) { - return Promise.reject(new AuthSdkError('Unable to retrieve OAuth redirect params from storage')); + if (sdk.options.pkce) { + // eslint-disable-next-line max-len + throw new AuthSdkError('Could not load PKCE codeVerifier from storage. This may indicate the auth flow has already completed or multiple auth flows are executing concurrently.', undefined); + } + throw new AuthSdkError('Unable to retrieve OAuth redirect params from storage'); } const urls: CustomUrls = oauthParams.urls as CustomUrls; delete oauthParams.urls; diff --git a/lib/server/serverStorage.ts b/lib/server/serverStorage.ts index b09929bd6..829d38b2d 100644 --- a/lib/server/serverStorage.ts +++ b/lib/server/serverStorage.ts @@ -88,11 +88,6 @@ class ServerStorage implements StorageUtil { return 'memory'; } - // will be removed in next version. OKTA-362589 - getHttpCache() { - return null; // stubbed in server.js - } - // shared in-memory using node cache getStorage(): SimpleStorage { return { diff --git a/lib/types/Storage.ts b/lib/types/Storage.ts index f872be7ab..cedebda41 100644 --- a/lib/types/Storage.ts +++ b/lib/types/Storage.ts @@ -39,18 +39,6 @@ export interface StorageProvider extends SimpleStorage { isSharedStorage(): boolean; } -// will be removed in next version. OKTA-362589 -export interface PKCEMeta { - codeVerifier: string; - redirectUri: string; -} - -// will be removed in next version. OKTA-362589 -export interface PKCEStorage extends StorageProvider { - setStorage(obj: PKCEMeta): void; - getStorage(): PKCEMeta; -} - export interface TransactionStorage extends StorageProvider { setStorage(obj: TransactionMeta): void; getStorage(): TransactionMeta; @@ -103,16 +91,6 @@ export interface BrowserStorageUtil extends StorageUtil { testStorage(storage: any): boolean; storage: Cookies; inMemoryStore: Record; - - // will be removed in next version. OKTA-362589 - getHttpCache(options?: StorageOptions): StorageProvider; - getPKCEStorage(options?: StorageOptions): PKCEStorage; -} - -export interface NodeStorageUtil extends StorageUtil { - // will be removed in next version. OKTA-362589 - getHttpCache(options?: StorageOptions): StorageProvider; - getStorage(): SimpleStorage; } // type StorageBuilder = (storage: Storage | SimpleStorage, name: string) => StorageProvider; diff --git a/lib/types/Transaction.ts b/lib/types/Transaction.ts index 2e83b2cf9..7c21007b5 100644 --- a/lib/types/Transaction.ts +++ b/lib/types/Transaction.ts @@ -18,7 +18,6 @@ import { IdxTransactionMeta } from '../idx/types'; export interface TransactionManagerOptions { storageManager?: StorageManager; enableSharedStorage?: boolean; // default true - legacyWidgetSupport?: boolean; // default true saveNonceCookie?: boolean; // default true saveStateCookie?: boolean; // default true saveParamsCookie?: boolean; // default true @@ -63,7 +62,6 @@ export type TransactionMeta = export interface TransactionMetaOptions extends Pick { - oauth?: boolean; muteWarning?: boolean; } diff --git a/test/spec/TransactionManager.ts b/test/spec/TransactionManager.ts index a98a58a69..c7de0c9f4 100644 --- a/test/spec/TransactionManager.ts +++ b/test/spec/TransactionManager.ts @@ -42,15 +42,11 @@ describe('TransactionManager', () => { beforeEach(() => { const transactionStorage = createMockStorage(); const idxResponseStorage = createMockStorage(); - const legacyPKCEStorage = createMockStorage(); - const legacyOAuthParamsStorage = createMockStorage(); const sharedTransactionStorage = createMockStorage(); const storageManager = { storageUtil: {}, getTransactionStorage: jest.fn().mockReturnValue(transactionStorage), getIdxResponseStorage: jest.fn().mockReturnValue(idxResponseStorage), - getLegacyPKCEStorage: jest.fn().mockReturnValue(legacyPKCEStorage), - getLegacyOAuthParamsStorage: jest.fn().mockReturnValue(legacyOAuthParamsStorage), getSharedTransactionStorage: jest.fn().mockReturnValue(sharedTransactionStorage) } as unknown as StorageManager; const options = { storageManager }; @@ -71,8 +67,6 @@ describe('TransactionManager', () => { storageManager, transactionStorage, idxResponseStorage, - legacyPKCEStorage, - legacyOAuthParamsStorage, sharedTransactionStorage, options, meta @@ -113,18 +107,6 @@ describe('TransactionManager', () => { expect(idxResponseStorage.clearStorage).not.toHaveBeenCalled(); }); - // This is for compatibility with older versions of the signin widget. OKTA-304806 - it('pkce: clears legacy PKCE meta', () => { - const { storageManager, transactionManager, legacyPKCEStorage } = testContext; - transactionManager.clear({ - pkce: true - }); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenCalledTimes(2); - expect(legacyPKCEStorage.clearStorage).toHaveBeenCalledTimes(2); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenNthCalledWith(1, { storageType: 'localStorage' }); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenNthCalledWith(2, { storageType: 'sessionStorage' }); - }); - describe('shared transaction storage', () => { beforeEach(() => { jest.spyOn(mocked.sharedStorage, 'clearTransactionFromSharedStorage'); @@ -172,165 +154,32 @@ describe('TransactionManager', () => { expect(transactionStorage.setStorage).toHaveBeenCalledWith(meta); }); - describe('oauth', () => { + describe('shared transaction storage', () => { beforeEach(() => { - const { storageManager } = testContext; - const cookieStorage = { - setItem: jest.fn() - }; - storageManager.getStorage = jest.fn().mockImplementation((options) => { - if (options.storageType !== 'cookie') { - throw new Error(`unexpected storage type ${options.storageType}`); - } - return cookieStorage; - }); - const sharedStorageObject = {}; - const sharedStorage = { - setStorage: jest.fn(), - getStorage: jest.fn().mockReturnValue(sharedStorageObject) - }; - storageManager.getSharedTansactionStorage = jest.fn().mockReturnValue(sharedStorage); - Object.assign(testContext, { - cookieStorage, - sharedStorage, - sharedStorageObject - }); + jest.spyOn(mocked.sharedStorage, 'saveTransactionToSharedStorage'); }); - - it('by default, saves 3 cookies: params, nonce, state', () => { + it('saves to shared transaction storage by default', () => { createInstance(); - const { transactionManager, meta, cookieStorage } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).toHaveBeenCalledTimes(3); - expect(cookieStorage.setItem).toHaveBeenNthCalledWith(1, - 'okta-oauth-redirect-params', - '{"responseType":"code","state":"mock-state","nonce":"mock-nonce","scopes":["a","b"],"clientId":"mock-clientid","urls":{"a":"b"},"ignoreSignature":true}', - null - ); - expect(cookieStorage.setItem).toHaveBeenNthCalledWith(2, - 'okta-oauth-nonce', - 'mock-nonce', - null - ); - expect(cookieStorage.setItem).toHaveBeenNthCalledWith(3, - 'okta-oauth-state', - 'mock-state', - null - ); - }); - - describe('saveParamsCookie', () => { - beforeEach(() => { - const { options } = testContext; - options.saveNonceCookie = false; - options.saveStateCookie = false; - }); - it('is enabled by default', () => { - createInstance(); - const { transactionManager, meta, cookieStorage } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).toHaveBeenCalledWith( - 'okta-oauth-redirect-params', - '{"responseType":"code","state":"mock-state","nonce":"mock-nonce","scopes":["a","b"],"clientId":"mock-clientid","urls":{"a":"b"},"ignoreSignature":true}', - null - ); - }); - it('can be disabled via option', () => { - createInstance({ saveParamsCookie: false }); - const { transactionManager, meta, cookieStorage } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).not.toHaveBeenCalled(); - }); - }); - - describe('saveNonceCookie', () => { - beforeEach(() => { - const { options } = testContext; - options.saveParamsCookie = false; - options.saveStateCookie = false; - }); - it('is enabled by default', () => { - createInstance(); - const { transactionManager, meta, cookieStorage } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).toHaveBeenCalledWith( - 'okta-oauth-nonce', - 'mock-nonce', - null - ); - }); - it('can be disabled via option', () => { - createInstance({ saveNonceCookie: false }); - const { transactionManager, meta, cookieStorage } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).not.toHaveBeenCalled(); - }); - it('will not set a cookie if there is no nonce', () => { - createInstance(); - const { transactionManager, meta, cookieStorage } = testContext; - delete meta.nonce; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).not.toHaveBeenCalled(); - }); + const { transactionManager, meta, storageManager } = testContext; + transactionManager.save(meta); + expect(mocked.sharedStorage.saveTransactionToSharedStorage).toHaveBeenCalledWith(storageManager, meta.state, meta); }); - - describe('saveStateCookie', () => { - beforeEach(() => { - const { options } = testContext; - options.saveParamsCookie = false; - options.saveNonceCookie = false; - }); - it('is enabled by default', () => { - createInstance(); - const { transactionManager, meta, cookieStorage } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).toHaveBeenCalledWith( - 'okta-oauth-state', - 'mock-state', - null - ); - }); - it('can be disabled via option', () => { - createInstance({ saveStateCookie: false }); - const { transactionManager, meta, cookieStorage } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).not.toHaveBeenCalled(); - }); - it('will not set a cookie if there is no state', () => { - createInstance(); - const { transactionManager, meta, cookieStorage } = testContext; - delete meta.state; - transactionManager.save(meta, { oauth: true }); - expect(cookieStorage.setItem).not.toHaveBeenCalled(); - }); + it('can be disabled via option', () => { + createInstance({ enableSharedStorage: false }); + const { transactionManager, meta } = testContext; + transactionManager.save(meta); + expect(mocked.sharedStorage.saveTransactionToSharedStorage).not.toHaveBeenCalled(); }); - - describe('shared transaction storage', () => { - beforeEach(() => { - jest.spyOn(mocked.sharedStorage, 'saveTransactionToSharedStorage'); - }); - it('saves to shared transaction storage by default', () => { - createInstance(); - const { transactionManager, meta, storageManager } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(mocked.sharedStorage.saveTransactionToSharedStorage).toHaveBeenCalledWith(storageManager, meta.state, meta); - }); - it('can be disabled via option', () => { - createInstance({ enableSharedStorage: false }); - const { transactionManager, meta } = testContext; - transactionManager.save(meta, { oauth: true }); - expect(mocked.sharedStorage.saveTransactionToSharedStorage).not.toHaveBeenCalled(); - }); - it('will not save if there is no state', () => { - createInstance(); - const { transactionManager, meta } = testContext; - delete meta.state; - transactionManager.save(meta, { oauth: true }); - expect(mocked.sharedStorage.saveTransactionToSharedStorage).not.toHaveBeenCalled(); - }); + it('will not save if there is no state', () => { + createInstance(); + const { transactionManager, meta } = testContext; + delete meta.state; + transactionManager.save(meta); + expect(mocked.sharedStorage.saveTransactionToSharedStorage).not.toHaveBeenCalled(); }); }); }); + describe('load', () => { beforeEach(() => { @@ -409,226 +258,6 @@ describe('TransactionManager', () => { }); }); - describe('pkce', () => { - it('pkce: true throws an error if meta cannot be found', () => { - createInstance(); - const { transactionManager } = testContext; - const fn = () => { - transactionManager.load({ - pkce: true - }); - }; - expect(fn).toThrowError('Could not load PKCE codeVerifier from storage'); - }); - it('pkce: false does not throw', () => { - createInstance(); - const { transactionManager } = testContext; - const fn = () => { - transactionManager.load({ - pkce: false - }); - }; - expect(fn).not.toThrow(); - }); - it('calls clearLegacyPKCE', () => { - createInstance(); - const { legacyPKCEStorage, transactionStorage, transactionManager, meta } = testContext; - jest.spyOn(transactionManager, 'clearLegacyPKCE').mockReturnValue(null); - jest.spyOn(transactionManager, 'loadLegacyPKCE').mockReturnValue({ - codeVerifier: 'abc' - }); - transactionStorage.getStorage.mockReturnValue({}); // nothing in transaction storage - legacyPKCEStorage.getStorage.mockReturnValue(meta); - transactionManager.load({ - pkce: true - }); - expect(transactionManager.clearLegacyPKCE).toHaveBeenCalledWith(); - }); - }); - - describe('oauth', () => { - it('oauth: true throws an error if params cannot be found', () => { - createInstance(); - const { transactionManager } = testContext; - jest.spyOn(transactionManager, 'loadLegacyOAuthParams'); - const fn = () => { - transactionManager.load({ - oauth: true - }); - }; - expect(fn).toThrowError('Unable to retrieve OAuth redirect params from storage'); - expect(transactionManager.loadLegacyOAuthParams).toHaveBeenCalledWith(); - }); - it('oauth: false does not throw', () => { - createInstance(); - const { transactionManager } = testContext; - jest.spyOn(transactionManager, 'loadLegacyOAuthParams'); - const fn = () => { - transactionManager.load({ - oauth: false - }); - }; - expect(fn).not.toThrow(); - expect(transactionManager.loadLegacyOAuthParams).not.toHaveBeenCalledWith(); - }); - it('calls clearLegacyOAuthParams', () => { - createInstance(); - const { transactionStorage, transactionManager } = testContext; - jest.spyOn(transactionManager, 'clearLegacyOAuthParams').mockReturnValue(null); - jest.spyOn(transactionManager, 'loadLegacyOAuthParams').mockReturnValue({ - redirectUri: 'http://fake' - }); - transactionStorage.getStorage.mockReturnValue({}); // no transaction data - transactionManager.load({ - oauth: true - }); - expect(transactionManager.clearLegacyOAuthParams).toHaveBeenCalledWith(); - }); - }); - - describe('pkce + oauth', () => { - it('throws an error if OAuth params cannot be found', () => { - createInstance(); - const { transactionManager } = testContext; - const fn = () => { - transactionManager.load({ - pkce: true, - oauth: true - }); - }; - expect(fn).toThrowError('Unable to retrieve OAuth redirect params from storage'); - }); - }); - - // This is for compatibility with older versions of the signin widget. OKTA-304806 - describe('if no transaction data, try to load from legacy PKCE meta', () => { - beforeEach(() => { - const { transactionStorage } = testContext; - transactionStorage.getStorage.mockReturnValue({}); // no transaction data - }); - - it('try localStorage first', () => { - createInstance(); - const { storageManager, transactionManager, meta } = testContext; - const getStorage = jest.fn().mockReturnValue(meta); - jest.spyOn(storageManager, 'getLegacyPKCEStorage').mockReturnValue({ - getStorage, - clearStorage: jest.fn() - }); - const res = transactionManager.load({ - pkce: true - }); - expect(res).toEqual(meta); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenCalledWith({ storageType: 'localStorage' }); - expect(getStorage).toHaveBeenCalledTimes(1); - }); - - it('check sessionStorage if localStorage has no data', () => { - createInstance(); - const { legacyPKCEStorage, storageManager, transactionManager, meta } = testContext; - legacyPKCEStorage.getStorage.mockReturnValueOnce({}); - legacyPKCEStorage.getStorage.mockReturnValueOnce(meta); - const res = transactionManager.load({ - pkce: true - }); - expect(res).toEqual(meta); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenNthCalledWith(1, { storageType: 'localStorage' }); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenNthCalledWith(2, { storageType: 'sessionStorage' }); - expect(legacyPKCEStorage.getStorage).toHaveBeenCalledTimes(2); - }); - }); - }); - - describe('loadLegacyPKCE', () => { - beforeEach(() => { - createInstance(); - const { storageManager } = testContext; - Object.assign(storageManager.storageUtil, { - testStorageType: jest.fn().mockReturnValue(true) - }); - }); - - it('try localStorage first', () => { - const { storageManager, transactionManager, legacyPKCEStorage, meta } = testContext; - legacyPKCEStorage.getStorage.mockReturnValue(meta); - const res = transactionManager.loadLegacyPKCE(); - expect(res).toEqual(meta); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenCalledTimes(1); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenNthCalledWith(1, { storageType: 'localStorage' }); - }); - - it('check sessionStorage if localStorage has no data', () => { - const { legacyPKCEStorage, storageManager, transactionManager, meta } = testContext; - const getStorage = legacyPKCEStorage.getStorage; - getStorage.mockReturnValueOnce({}); - getStorage.mockReturnValueOnce(meta); - const res = transactionManager.loadLegacyPKCE(); - expect(res).toEqual(meta); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenNthCalledWith(1, { storageType: 'localStorage' }); - expect(storageManager.getLegacyPKCEStorage).toHaveBeenNthCalledWith(2, { storageType: 'sessionStorage' }); - expect(getStorage).toHaveBeenCalledTimes(2); - }); - }); - - describe('loadLegacyOAuthParams', () => { - beforeEach(() => { - const fakeParams = { fake: 'fake', redirectUri: 'http://alsofake' }; - createInstance(); - const { storageManager } = testContext; - Object.assign(storageManager.storageUtil, { - testStorageType: jest.fn() - }); - Object.assign(testContext, { - fakeParams - }); - }); - - describe('has sessionStorage', () => { - it('should read from sessionStorage', () => { - const { storageManager, legacyOAuthParamsStorage, fakeParams, transactionManager } = testContext; - storageManager.storageUtil.testStorageType.mockReturnValueOnce(true); - legacyOAuthParamsStorage.getStorage.mockReturnValue(fakeParams); - const res = transactionManager.loadLegacyOAuthParams(); - expect(res).toEqual(fakeParams); - expect(storageManager.getLegacyOAuthParamsStorage).toHaveBeenCalledTimes(1); - expect(storageManager.getLegacyOAuthParamsStorage).toHaveBeenCalledWith({ storageType: 'sessionStorage' }); - }); - - it('should read from cookies when no data in sessionStorage', () => { - const { storageManager, legacyOAuthParamsStorage, fakeParams, transactionManager } = testContext; - storageManager.storageUtil.testStorageType.mockReturnValue(true); - legacyOAuthParamsStorage.getStorage.mockReturnValueOnce({}); - legacyOAuthParamsStorage.getStorage.mockReturnValueOnce(fakeParams); - const res = transactionManager.loadLegacyOAuthParams(); - expect(res).toEqual(fakeParams); - expect(storageManager.getLegacyOAuthParamsStorage).toHaveBeenCalledTimes(2); - expect(storageManager.getLegacyOAuthParamsStorage).toHaveBeenNthCalledWith(1, { storageType: 'sessionStorage' }); - expect(storageManager.getLegacyOAuthParamsStorage).toHaveBeenNthCalledWith(2, { storageType: 'cookie' }); - }); - }); - - describe('not has sessionStorage', () => { - it('should read from cookies', () => { - const { storageManager, legacyOAuthParamsStorage, fakeParams, transactionManager } = testContext; - storageManager.storageUtil.testStorageType.mockReturnValueOnce(false); - storageManager.storageUtil.testStorageType.mockReturnValueOnce(true); - legacyOAuthParamsStorage.getStorage.mockReturnValue(fakeParams); - const res = transactionManager.loadLegacyOAuthParams(); - expect(res).toEqual(fakeParams); - expect(storageManager.getLegacyOAuthParamsStorage).toHaveBeenCalledTimes(1); - expect(storageManager.getLegacyOAuthParamsStorage).toHaveBeenNthCalledWith(1, { storageType: 'cookie' }); - }); - }); - - describe('no data in session or cookie', () => { - it('throws', () => { - const { transactionManager } = testContext; - const fn = () => { - transactionManager.loadLegacyOAuthParams(); - }; - expect(fn).toThrowError('Unable to retrieve OAuth redirect params from storage'); - }); - }); }); describe('saveIdxResponse', () => { diff --git a/test/spec/oidc/getWithRedirect.ts b/test/spec/oidc/getWithRedirect.ts index 8cd15e0aa..51bcd3404 100644 --- a/test/spec/oidc/getWithRedirect.ts +++ b/test/spec/oidc/getWithRedirect.ts @@ -73,12 +73,12 @@ describe('getWithRedirect', () => { jest.spyOn(sdk.transactionManager, 'save'); }); - it('saves using the oauth option', async () => { + it('saves the transaction meta', async () => { const { sdk, meta } = testContext; const issuer = 'http://fake'; sdk.options.issuer = issuer; await getWithRedirect(sdk, {}); - expect(sdk.transactionManager.save).toHaveBeenCalledWith(meta, { oauth: true }); + expect(sdk.transactionManager.save).toHaveBeenCalledWith(meta); }); }); diff --git a/test/spec/oidc/getWithRedirectLegacy.ts b/test/spec/oidc/getWithRedirectLegacy.ts index 832af5398..242daedf7 100644 --- a/test/spec/oidc/getWithRedirectLegacy.ts +++ b/test/spec/oidc/getWithRedirectLegacy.ts @@ -34,26 +34,10 @@ import oauthUtil from '@okta/test.support/oauthUtil'; import * as token from '../../../lib/oidc'; const pkce = token.pkce; -// Expected settings when testing on HTTP protocol -var insecureCookieSettings = { - secure: false, - sameSite: 'lax' -}; - -// Expected settings when testing on HTTPS protocol -var secureCookieSettings = { - secure: true, - sameSite: 'none' -}; - // eslint-disable-next-line max-statements describe('token.getWithRedirect', function() { var codeChallengeMethod = 'S256'; var codeChallenge = 'fake'; - var defaultUrls; - var customUrls; - var nonceCookie; - var stateCookie; var originalLocation; afterEach(() => { @@ -70,36 +54,6 @@ describe('token.getWithRedirect', function() { protocol: 'https:', hostname: 'somesite.local' } as Location; - - defaultUrls = { - issuer: 'https://auth-js-test.okta.com', - authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', - userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo', - tokenUrl: 'https://auth-js-test.okta.com/oauth2/v1/token', - revokeUrl: 'https://auth-js-test.okta.com/oauth2/v1/revoke', - logoutUrl: 'https://auth-js-test.okta.com/oauth2/v1/logout', - }; - customUrls = { - issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7', - authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', - userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo', - tokenUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/token', - revokeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/revoke', - logoutUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/logout', - }; - nonceCookie = [ - 'okta-oauth-nonce', - oauthUtil.mockedNonce, - null, // expiresAt - secureCookieSettings - ]; - - stateCookie = [ - 'okta-oauth-state', - oauthUtil.mockedState, - null, // expiresAt - secureCookieSettings - ]; }); afterEach(() => { @@ -115,51 +69,6 @@ describe('token.getWithRedirect', function() { spyOn(TransactionManager.prototype, 'save').and.callThrough(); spyOn(pkce, 'computeChallenge').and.returnValue(Promise.resolve(codeChallenge)); } - it('Uses insecure cookie settings if running on http://localhost', function() { - delete (window as any).location; - window.location = { - protocol: 'http:', - hostname: 'localhost' - } as Location; - return oauthUtil.setupRedirect({ - getWithRedirectArgs: {}, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, - insecureCookieSettings - ], - [ - 'okta-oauth-nonce', - oauthUtil.mockedNonce, - null, // expiresAt - insecureCookieSettings - ], - [ - 'okta-oauth-state', - oauthUtil.mockedState, - null, // expiresAt - insecureCookieSettings - ] - ], - expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + - 'client_id=NPSfOkH5eZrTy8PMDlvx&' + - 'nonce=' + oauthUtil.mockedNonce + '&' + - 'redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&' + - 'response_type=token%20id_token&' + - 'state=' + oauthUtil.mockedState + '&' + - 'scope=openid%20email' - }); - }); it('If extra options are passed, promise will reject', function() { return oauthUtil.setupRedirect({ @@ -198,22 +107,7 @@ describe('token.getWithRedirect', function() { getWithRedirectArgs: { responseMode: 'fragment', }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'code', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'code_challenge=' + codeChallenge + '&' + @@ -235,22 +129,7 @@ describe('token.getWithRedirect', function() { responseMode: 'fragment' }, getWithRedirectArgs: {}, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'code', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'code_challenge=' + codeChallenge + '&' + @@ -269,22 +148,7 @@ describe('token.getWithRedirect', function() { getWithRedirectArgs: { sessionToken: 'testToken' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -307,22 +171,7 @@ describe('token.getWithRedirect', function() { getWithRedirectArgs: { sessionToken: 'testToken' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: customUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -348,22 +197,7 @@ describe('token.getWithRedirect', function() { sessionToken: 'testToken', issuer: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7' }], - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'token', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: customUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -382,22 +216,7 @@ describe('token.getWithRedirect', function() { scopes: ['email'], sessionToken: 'testToken' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'token', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -422,22 +241,7 @@ describe('token.getWithRedirect', function() { scopes: ['email'], sessionToken: 'testToken' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'token', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: customUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -455,22 +259,7 @@ describe('token.getWithRedirect', function() { responseType: ['token', 'id_token'], idp: 'testIdp' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'idp=testIdp&' + @@ -494,22 +283,7 @@ describe('token.getWithRedirect', function() { responseType: ['token', 'id_token'], idp: 'testIdp' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: customUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'idp=testIdp&' + @@ -527,22 +301,7 @@ describe('token.getWithRedirect', function() { sessionToken: 'testToken', responseType: 'code' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'code', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -563,22 +322,7 @@ describe('token.getWithRedirect', function() { getWithRedirectArgs: { sessionToken: 'testToken', }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'code', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'code_challenge=' + codeChallenge + '&' + @@ -604,22 +348,7 @@ describe('token.getWithRedirect', function() { sessionToken: 'testToken', responseType: 'code' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'code', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: customUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -638,22 +367,7 @@ describe('token.getWithRedirect', function() { sessionToken: 'testToken', responseType: ['code'] }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['code'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -676,24 +390,7 @@ describe('token.getWithRedirect', function() { sessionToken: 'testToken', responseType: ['code'] }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'code', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, - secureCookieSettings - ], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'code_challenge=' + codeChallenge + '&' + @@ -714,22 +411,7 @@ describe('token.getWithRedirect', function() { responseType: 'code', responseMode: 'form_post' }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: 'code', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'nonce=' + oauthUtil.mockedNonce + '&' + @@ -747,22 +429,7 @@ describe('token.getWithRedirect', function() { getWithRedirectArgs: { loginHint: 'JoeUser', }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'login_hint=JoeUser&' + @@ -779,22 +446,7 @@ describe('token.getWithRedirect', function() { getWithRedirectArgs: { idpScope: 'scope1 scope2', }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'idp_scope=scope1%20scope2&' + @@ -811,22 +463,7 @@ describe('token.getWithRedirect', function() { getWithRedirectArgs: { idpScope: ['scope1', 'scope2'], }, - expectedCookies: [ - [ - 'okta-oauth-redirect-params', - JSON.stringify({ - responseType: ['token', 'id_token'], - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - clientId: 'NPSfOkH5eZrTy8PMDlvx', - urls: defaultUrls, - ignoreSignature: false - }), - null, secureCookieSettings], - nonceCookie, - stateCookie - ], + expectedCookies: [], expectedRedirectUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize?' + 'client_id=NPSfOkH5eZrTy8PMDlvx&' + 'idp_scope=scope1%20scope2&' + diff --git a/test/spec/oidc/parseFromUrl.ts b/test/spec/oidc/parseFromUrl.ts index fa7dda413..9fd95375b 100644 --- a/test/spec/oidc/parseFromUrl.ts +++ b/test/spec/oidc/parseFromUrl.ts @@ -36,7 +36,7 @@ describe('token.parseFromUrl', function() { var redirectUri = 'https://example.com/redirect'; spyOn(OktaAuth.features, 'isPKCESupported').and.returnValue(true); - spyOn(TransactionManager.prototype, 'loadLegacyPKCE').and.returnValue({ + spyOn(TransactionManager.prototype, 'load').and.returnValue({ codeVerifier, redirectUri }); @@ -53,7 +53,7 @@ describe('token.parseFromUrl', function() { }, searchMock: '?code=fake' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['code'], state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -64,7 +64,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { code: 'fake', state: oauthUtil.mockedState, @@ -78,7 +78,7 @@ describe('token.parseFromUrl', function() { parseFromUrlArgs: 'http://example.com#id_token=' + tokens.standardIdToken + '&access_token=' + tokens.standardAccessToken + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['token', 'id_token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -89,7 +89,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -107,7 +107,7 @@ describe('token.parseFromUrl', function() { '&access_token=' + tokens.standardAccessToken + '&state=' + oauthUtil.mockedState, }, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['token', 'id_token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -118,7 +118,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -140,7 +140,8 @@ describe('token.parseFromUrl', function() { }, searchMock: '?code=fake' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { + codeVerifier: 'foo', responseType: ['token', 'id_token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -151,7 +152,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, calls: [ { request: { @@ -185,7 +186,8 @@ describe('token.parseFromUrl', function() { }, hashMock: '#code=fake' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { + codeVerifier: 'foo', responseType: ['token', 'id_token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -196,7 +198,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { code: 'fake', state: oauthUtil.mockedState, @@ -220,7 +222,8 @@ describe('token.parseFromUrl', function() { }, hashMock: '#code=fake' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { + codeVerifier: 'foo', responseType: ['token', 'id_token'], state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -231,7 +234,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { code: 'fake', state: oauthUtil.mockedState, @@ -252,7 +255,7 @@ describe('token.parseFromUrl', function() { noHistory: true, hashMock: '#id_token=' + tokens.standardIdToken + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: 'id_token', state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -263,7 +266,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -282,7 +285,7 @@ describe('token.parseFromUrl', function() { return oauthUtil.setupParseUrl({ hashMock: '#id_token=' + tokens.standardIdToken + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: 'id_token', state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -293,7 +296,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -312,7 +315,7 @@ describe('token.parseFromUrl', function() { return oauthUtil.setupParseUrl({ hashMock: '#id_token=' + tokens.authServerIdToken + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: 'id_token', state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -323,7 +326,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -340,7 +343,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: 'token', state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -351,7 +354,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -368,7 +371,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: 'token', state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -379,7 +382,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -397,7 +400,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -408,7 +411,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -427,7 +430,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -438,7 +441,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' } - }), + }, expectedResp: { state: oauthUtil.mockedState, tokens: { @@ -463,7 +466,7 @@ describe('token.parseFromUrl', function() { willFail: true, shouldClearTransaction: false, hashMock: '', - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -474,7 +477,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }) + } }) .catch(function(e) { util.expectErrorToEqual(e, error); @@ -482,32 +485,6 @@ describe('token.parseFromUrl', function() { }); - it('throws an error if no oauth redirect params are set', () => { - const error = { - name: 'AuthSdkError', - message: 'Unable to retrieve OAuth redirect params from storage', - errorCode: 'INTERNAL', - errorSummary: 'Unable to retrieve OAuth redirect params from storage', - errorLink: 'INTERNAL', - errorId: 'INTERNAL', - errorCauses: [] - }; - - return oauthUtil.setupParseUrl({ - willFail: true, - shouldClearTransaction: false, - hashMock: '#access_token=' + tokens.standardAccessToken + - '&id_token=' + tokens.standardIdToken + - '&expires_in=3600' + - '&token_type=Bearer' + - '&state=' + oauthUtil.mockedState, - oauthParams: '' - }) - .catch(function(e) { - util.expectErrorToEqual(e, error); - }); - }); - it('throws an error if state doesn\'t match', () => { const error = { name: 'AuthSdkError', @@ -526,7 +503,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: 'mismatchedState', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -537,7 +514,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }) + } }) .catch(function(e) { util.expectErrorToEqual(e, error); @@ -561,7 +538,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'mismatchedNonce', @@ -572,7 +549,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }) + } }) .catch(function(e) { util.expectErrorToEqual(e, error); @@ -595,7 +572,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -606,7 +583,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }) + } }) .catch(function(e) { util.expectErrorToEqual(e, error); @@ -629,7 +606,7 @@ describe('token.parseFromUrl', function() { '&expires_in=3600' + '&token_type=Bearer' + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: oauthUtil.mockedState, nonce: oauthUtil.mockedNonce, @@ -640,7 +617,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }) + } }) .catch(function(e) { util.expectErrorToEqual(e, error); @@ -659,7 +636,7 @@ describe('token.parseFromUrl', function() { return oauthUtil.setupParseUrl({ willFail: true, hashMock: '#error=fake_error&error_description=fake_description', - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -670,14 +647,14 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }) + } }) .catch(function(e) { util.expectErrorToEqual(e, error); }); }); - it('throws an error if no transaction meta and legacyWidgetSupport is false', () => { + it('throws an error if no transaction meta', () => { const error = { name: 'AuthSdkError', message: 'Unable to retrieve OAuth redirect params from storage', @@ -687,28 +664,35 @@ describe('token.parseFromUrl', function() { errorId: 'INTERNAL', errorCauses: [] }; + return oauthUtil.setupParseUrl({ + shouldClearTransaction: false, + willFail: true, + hashMock: '#id_token=' + tokens.standardIdToken + + '&state=' + oauthUtil.mockedState, + }) + .catch(function(e) { + util.expectErrorToEqual(e, error); + }); + }); + + it('PKCE: throws an error if no transaction meta', () => { + const error = { + name: 'AuthSdkError', + message: 'Could not load PKCE codeVerifier from storage. This may indicate the auth flow has already completed or multiple auth flows are executing concurrently.', + errorCode: 'INTERNAL', + errorSummary: 'Could not load PKCE codeVerifier from storage. This may indicate the auth flow has already completed or multiple auth flows are executing concurrently.', + errorLink: 'INTERNAL', + errorId: 'INTERNAL', + errorCauses: [] + }; return oauthUtil.setupParseUrl({ oktaAuthArgs: { - transactionManager: { - legacyWidgetSupport: false - } + pkce: true }, shouldClearTransaction: false, willFail: true, hashMock: '#id_token=' + tokens.standardIdToken + '&state=' + oauthUtil.mockedState, - oauthParams: JSON.stringify({ - responseType: 'id_token', - state: oauthUtil.mockedState, - nonce: oauthUtil.mockedNonce, - scopes: ['openid', 'email'], - urls: { - issuer: 'https://auth-js-test.okta.com', - tokenUrl: 'https://auth-js-test.okta.com/oauth2/v1/token', - authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', - userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' - } - }), }) .catch(function(e) { util.expectErrorToEqual(e, error); @@ -729,7 +713,7 @@ describe('token.parseFromUrl', function() { willFail: true, shouldClearTransaction: false, hashMock: '#error=interaction_required&error_description=fake_description', - oauthParams: JSON.stringify({ + savedTransaction: { responseType: ['id_token', 'token'], state: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', nonce: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', @@ -740,7 +724,7 @@ describe('token.parseFromUrl', function() { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/v1/userinfo' } - }) + } }) .catch(function(e) { util.expectErrorToEqual(e, error); diff --git a/test/spec/oidc/util/oauth.ts b/test/spec/oidc/util/oauth.ts index 6f08085bf..23161c281 100644 --- a/test/spec/oidc/util/oauth.ts +++ b/test/spec/oidc/util/oauth.ts @@ -170,9 +170,6 @@ describe('getOAuthUrls', function() { }); it('allows token requested with only authorizeUrl and userinfoUrl', function() { setupOAuthUrls({ - oauthParams: { - responseType: 'token' - }, options: { authorizeUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/authorize', userinfoUrl: 'https://auth-js-test.okta.com/oauth2/aus8aus76q8iphupD0h7/v1/userinfo' diff --git a/test/support/oauthUtil.js b/test/support/oauthUtil.js index 4f227e9e0..189554374 100644 --- a/test/support/oauthUtil.js +++ b/test/support/oauthUtil.js @@ -503,17 +503,7 @@ oauthUtil.setupParseUrl = function(opts) { }); } - util.mockGetCookie(opts.oauthParams); - var deleteCookieMock = util.mockDeleteCookie(); - - jest.spyOn(storageUtil, 'getSessionStorage') - .mockImplementation(() => ({ - getItem: jest.fn().mockReturnValue(opts.oauthParams || ''), - removeItem: jest.fn() - })); - jest.spyOn(storageUtil, 'browserHasSessionStorage') - .mockImplementation(() => !!opts.hasSessionStorage); - + jest.spyOn(client.transactionManager, 'load').mockReturnValue(opts.savedTransaction); jest.spyOn(client.transactionManager, 'clear'); return client.token.parseFromUrl(opts.parseFromUrlArgs) @@ -521,9 +511,6 @@ oauthUtil.setupParseUrl = function(opts) { var expectedResp = opts.expectedResp; validateResponse(res, expectedResp); - // The cookie should be deleted - expect(deleteCookieMock).toHaveBeenCalledWith('okta-oauth-redirect-params'); - if (opts.parseFromUrlArgs && (typeof opts.parseFromUrlArgs === 'string' || opts.parseFromUrlArgs.url)) { expect(setLocationHashSpy).not.toHaveBeenCalled(); expect(replaceStateSpy).not.toHaveBeenCalled();