From ecff936b010da4f137737a107fdd004d26525b86 Mon Sep 17 00:00:00 2001 From: Steve Hobbs Date: Mon, 17 Feb 2020 13:59:53 +0000 Subject: [PATCH] [SDK-1352] Stop checking `isAuthenticated` cookie on initialization when using local storage (#352) * Changes to the initialization strategy * Removed unused import from a test --- __tests__/index.test.ts | 50 ++++++++++++++++++++++++++--------------- src/Auth0Client.ts | 20 ++++++++++------- src/constants.ts | 3 +++ src/global.ts | 7 +++++- src/index.ts | 13 ++++++----- 5 files changed, 60 insertions(+), 33 deletions(-) diff --git a/__tests__/index.test.ts b/__tests__/index.test.ts index 6ab19da26..47021f9f8 100644 --- a/__tests__/index.test.ts +++ b/__tests__/index.test.ts @@ -5,10 +5,9 @@ jest.mock('../src/transaction-manager'); jest.mock('../src/utils'); import Auth0Client from '../src/Auth0Client'; -import createAuth0Client, { - PopupConfigOptions, - GetTokenSilentlyOptions -} from '../src/index'; +import { CacheLocation } from '../src/global'; + +import createAuth0Client, { GetTokenSilentlyOptions } from '../src/index'; import { AuthenticationError } from '../src/errors'; import version from '../src/version'; @@ -55,7 +54,8 @@ const mockEnclosedCache = { jest.mock('../src/cache', () => ({ InMemoryCache: () => ({ enclosedCache: mockEnclosedCache - }) + }), + LocalStorageCache: () => mockEnclosedCache })); const setup = async (options = {}) => { @@ -1913,14 +1913,11 @@ describe('default creation function', () => { client_id: TEST_CLIENT_ID }); - expect(auth0.getTokenSilently).toHaveBeenCalledWith({ - audience: undefined, - ignoreCache: true - }); + expect(auth0.getTokenSilently).toHaveBeenCalledWith(); }); describe('when refresh tokens are not used', () => { - it('calls getTokenSilently with audience and scope', async () => { + it('calls getTokenSilently', async () => { const utils = require('../src/utils'); const options = { @@ -1939,10 +1936,7 @@ describe('default creation function', () => { ...options }); - expect(auth0.getTokenSilently).toHaveBeenCalledWith({ - ignoreCache: true, - ...options - }); + expect(auth0.getTokenSilently).toHaveBeenCalledWith(); }); }); @@ -1972,11 +1966,31 @@ describe('default creation function', () => { 'offline_access' ); - expect(auth0.getTokenSilently).toHaveBeenCalledWith({ - ignoreCache: true, - scope: 'the-scope offline_access', - audience: 'the-audience' + expect(auth0.getTokenSilently).toHaveBeenCalledWith(); + }); + }); + + describe('when localstorage is used', () => { + it('refreshes token state regardless of isauthenticated cookie', async () => { + const cacheLocation: CacheLocation = 'localstorage'; + + const options = { + audience: 'the-audience', + scope: 'the-scope', + cacheLocation + }; + + Auth0Client.prototype.getTokenSilently = jest.fn(); + + require('../src/storage').get = () => false; + + const auth0 = await createAuth0Client({ + domain: TEST_DOMAIN, + client_id: TEST_CLIENT_ID, + ...options }); + + expect(auth0.getTokenSilently).toHaveBeenCalledWith(); }); }); }); diff --git a/src/Auth0Client.ts b/src/Auth0Client.ts index acf97789b..14e8a250c 100644 --- a/src/Auth0Client.ts +++ b/src/Auth0Client.ts @@ -38,7 +38,8 @@ import { GetTokenWithPopupOptions, LogoutOptions, RefreshTokenOptions, - OAuthTokenOptions + OAuthTokenOptions, + CacheLocation } from './global'; /** @@ -54,13 +55,16 @@ const GET_TOKEN_SILENTLY_LOCK_KEY = 'auth0.lock.getTokenSilently'; /** * @ignore */ -const cacheFactory = location => { - const builders = { - memory: () => new InMemoryCache().enclosedCache, - localstorage: () => new LocalStorageCache() - }; +const cacheLocationBuilders = { + memory: () => new InMemoryCache().enclosedCache, + localstorage: () => new LocalStorageCache() +}; - return builders[location]; +/** + * @ignore + */ +const cacheFactory = (location: string) => { + return cacheLocationBuilders[location]; }; /** @@ -73,7 +77,7 @@ export default class Auth0Client { private tokenIssuer: string; private readonly DEFAULT_SCOPE = 'openid profile email'; - cacheLocation: string; + cacheLocation: CacheLocation; constructor(private options: Auth0ClientOptions) { this.cacheLocation = options.cacheLocation || 'memory'; diff --git a/src/constants.ts b/src/constants.ts index b9fdd72b4..6b8fa8a87 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -22,3 +22,6 @@ export const DEFAULT_SILENT_TOKEN_RETRY_COUNT = 3; * @ignore */ export const DEFAULT_FETCH_TIMEOUT_MS = 10000; + +export const CACHE_LOCATION_MEMORY = 'memory'; +export const CACHE_LOCATION_LOCAL_STORAGE = 'localstorage'; diff --git a/src/global.ts b/src/global.ts index 04eff896a..b0bdde39b 100644 --- a/src/global.ts +++ b/src/global.ts @@ -95,7 +95,7 @@ export interface Auth0ClientOptions extends BaseLoginOptions { * The location to use when storing cache data. Valid values are `memory` or `localstorage`. * The default setting is `memory`. */ - cacheLocation?: 'memory' | 'localstorage'; + cacheLocation?: CacheLocation; /** * If true, refresh tokens are used to fetch new access tokens from the Auth0 server. If false, the legacy technique of using a hidden iframe and the `authorization_code` grant with `prompt=none` is used. @@ -112,6 +112,11 @@ export interface Auth0ClientOptions extends BaseLoginOptions { authorizeTimeoutInSeconds?: number; } +/** + * The possible locations where tokens can be stored + */ +export type CacheLocation = 'memory' | 'localstorage'; + /** * @ignore */ diff --git a/src/index.ts b/src/index.ts index 0d82cf68d..c16e7670d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,8 @@ import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'; import Auth0Client from './Auth0Client'; import * as ClientStorage from './storage'; import { Auth0ClientOptions } from './global'; +import { CACHE_LOCATION_MEMORY } from './constants'; + import './global'; import { validateCrypto, getUniqueScopes } from './utils'; @@ -26,16 +28,15 @@ export default async function createAuth0Client(options: Auth0ClientOptions) { const auth0 = new Auth0Client(options); - if (!ClientStorage.get('auth0.is.authenticated')) { + if ( + auth0.cacheLocation === CACHE_LOCATION_MEMORY && + !ClientStorage.get('auth0.is.authenticated') + ) { return auth0; } try { - await auth0.getTokenSilently({ - audience: options.audience, - scope: options.scope, - ignoreCache: true - }); + await auth0.getTokenSilently(); } catch (error) { // ignore }