Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

removes legacy PKCE and OAuth storage #1181

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions lib/OktaAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,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()) {
Expand Down
21 changes: 3 additions & 18 deletions lib/StorageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}
183 changes: 0 additions & 183 deletions lib/TransactionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
} from './types';
import { isRawIdxResponse } from './idx/types/idx-js';
Expand All @@ -41,20 +35,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;
Expand All @@ -78,19 +64,6 @@ export default class TransactionManager {
clearTransactionFromSharedStorage(this.storageManager, state);
}
}

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
Expand All @@ -115,47 +88,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 {
Expand Down Expand Up @@ -189,124 +121,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({ rawIdxResponse, requestDidSucceed }: SavedIdxResponse): void {
if (!this.saveLastResponse) {
return;
Expand Down
11 changes: 0 additions & 11 deletions lib/browser/browserStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
import Cookies from 'js-cookie';
import AuthSdkError from '../errors/AuthSdkError';
import {
StorageProvider,
StorageOptions,
PKCEStorage,
CookieOptions,
SimpleStorage,
StorageType,
Expand All @@ -29,15 +27,6 @@ import { warn } from '../util';
// 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() {
Expand Down
3 changes: 0 additions & 3 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion lib/oidc/getWithRedirect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ export async function getWithRedirect(sdk: OktaAuthInterface, options?: TokenPar
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);
}
8 changes: 5 additions & 3 deletions lib/oidc/parseFromUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 0 additions & 5 deletions lib/server/serverStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading