From 72d8d821c2456a09ece458670f0a1b3cd718322e Mon Sep 17 00:00:00 2001 From: Frederik Prijck Date: Fri, 13 Nov 2020 09:24:41 +0100 Subject: [PATCH] [SDK-2047] Move and refactor handleRedirectCallback tests (#640) --- __tests__/Auth0Client.helpers.ts | 38 +++- __tests__/Auth0Client.test.ts | 370 ++++++++++++++++++++++++++++++- __tests__/index.test.ts | 370 +------------------------------ 3 files changed, 399 insertions(+), 379 deletions(-) diff --git a/__tests__/Auth0Client.helpers.ts b/__tests__/Auth0Client.helpers.ts index 14c07d3f9..24bfdeef5 100644 --- a/__tests__/Auth0Client.helpers.ts +++ b/__tests__/Auth0Client.helpers.ts @@ -73,7 +73,9 @@ const processDefaultLoginWithRedirectOptions = config => { return { token, - authorize + authorize, + useHash: config.useHash, + customCallbackUrl: config.customCallbackUrl }; }; @@ -90,7 +92,10 @@ export const loginWithRedirectFn = (mockWindow, mockFetch, fetchResponse) => { code?: string; state?: string; error?: string; + errorDescription?: string; }; + useHash?: boolean; + customCallbackUrl?: string; } = { token: {}, authorize: {} @@ -98,15 +103,35 @@ export const loginWithRedirectFn = (mockWindow, mockFetch, fetchResponse) => { ) => { const { token, - authorize: { code, state, error } + authorize: { code, state, error, errorDescription }, + useHash, + customCallbackUrl } = processDefaultLoginWithRedirectOptions(testConfig); await auth0.loginWithRedirect(options); expect(mockWindow.location.assign).toHaveBeenCalled(); - if (error) { - window.history.pushState({}, '', `/?error=${error}&state=${state}`); + if (error && errorDescription) { + window.history.pushState( + {}, + '', + `/${ + useHash ? '#' : '' + }?error=${error}&error_description=${errorDescription}&state=${state}` + ); + } else if (error) { + window.history.pushState( + {}, + '', + `/${useHash ? '#' : ''}?error=${error}&state=${state}` + ); + } else if (code) { + window.history.pushState( + {}, + '', + `/${useHash ? '#' : ''}?code=${code}&state=${state}` + ); } else { - window.history.pushState({}, '', `/?code=${code}&state=${state}`); + window.history.pushState({}, '', `/`); } mockFetch.mockResolvedValueOnce( @@ -123,7 +148,8 @@ export const loginWithRedirectFn = (mockWindow, mockFetch, fetchResponse) => { ) ) ); - await auth0.handleRedirectCallback(); + + return await auth0.handleRedirectCallback(customCallbackUrl); }; }; diff --git a/__tests__/Auth0Client.test.ts b/__tests__/Auth0Client.test.ts index 42ae36dcc..c4a57b78d 100644 --- a/__tests__/Auth0Client.test.ts +++ b/__tests__/Auth0Client.test.ts @@ -428,6 +428,7 @@ describe('Auth0Client', () => { }) ); }); + it('calls `tokenVerifier.verify` with the `leeway` from constructor', async () => { const auth0 = setup({ leeway: 10 }); @@ -439,6 +440,7 @@ describe('Auth0Client', () => { }) ); }); + it('calls `tokenVerifier.verify` with undefined `max_age` when value set in constructor is an empty string', async () => { const auth0 = setup({ max_age: '' }); @@ -450,6 +452,7 @@ describe('Auth0Client', () => { }) ); }); + it('calls `tokenVerifier.verify` with the parsed `max_age` string from constructor', async () => { const auth0 = setup({ max_age: '10' }); @@ -461,6 +464,7 @@ describe('Auth0Client', () => { }) ); }); + it('calls `tokenVerifier.verify` with the parsed `max_age` number from constructor', async () => { const auth0 = setup({ max_age: 10 }); @@ -551,6 +555,7 @@ describe('Auth0Client', () => { }) ); }); + it('should save refresh_token in local storage cache', async () => { const auth0 = setup({ useRefreshTokens: true, @@ -589,6 +594,7 @@ describe('Auth0Client', () => { } ); }); + it('saves `auth0.is.authenticated` key in storage for an extended period', async () => { const auth0 = setup({ sessionCheckExpiryDays: 2 @@ -648,6 +654,63 @@ describe('Auth0Client', () => { }); }); + it('should log the user in and get the token with a custom callback url', async () => { + const auth0 = setup(); + + await loginWithRedirect( + auth0, + {}, + { + useHash: true, + customCallbackUrl: `https://test.auth0.com?code=${TEST_CODE}&state=${TEST_STATE}` + } + ); + + const url = new URL(mockWindow.location.assign.mock.calls[0][0]); + assertUrlEquals(url, TEST_DOMAIN, '/authorize', { + client_id: TEST_CLIENT_ID, + redirect_uri: TEST_REDIRECT_URI, + scope: TEST_SCOPES, + response_type: 'code', + response_mode: 'query', + state: TEST_STATE, + nonce: TEST_NONCE, + code_challenge: TEST_CODE_CHALLENGE, + code_challenge_method: 'S256' + }); + assertPost('https://auth0_domain/oauth/token', { + redirect_uri: TEST_REDIRECT_URI, + client_id: TEST_CLIENT_ID, + code_verifier: TEST_CODE_VERIFIER, + grant_type: 'authorization_code', + code: TEST_CODE + }); + }); + + it('should log the user in and get the token when using hash', async () => { + const auth0 = setup(); + await loginWithRedirect(auth0, {}, { useHash: true }); + const url = new URL(mockWindow.location.assign.mock.calls[0][0]); + assertUrlEquals(url, TEST_DOMAIN, '/authorize', { + client_id: TEST_CLIENT_ID, + redirect_uri: TEST_REDIRECT_URI, + scope: TEST_SCOPES, + response_type: 'code', + response_mode: 'query', + state: TEST_STATE, + nonce: TEST_NONCE, + code_challenge: TEST_CODE_CHALLENGE, + code_challenge_method: 'S256' + }); + assertPost('https://auth0_domain/oauth/token', { + redirect_uri: TEST_REDIRECT_URI, + client_id: TEST_CLIENT_ID, + code_verifier: TEST_CODE_VERIFIER, + grant_type: 'authorization_code', + code: TEST_CODE + }); + }); + it('should log the user in and get the user', async () => { const auth0 = setup({ scope: 'foo' }); await loginWithRedirect(auth0); @@ -730,6 +793,108 @@ describe('Auth0Client', () => { 'HTTP error. Unable to fetch https://auth0_domain/oauth/token' ); }); + + it('calls `tokenVerifier.verify` with the `id_token` from in the oauth/token response', async () => { + const auth0 = setup({ + issuer: 'test-123.auth0.com' + }); + + await loginWithRedirect(auth0); + expect(tokenVerifier).toHaveBeenCalledWith( + expect.objectContaining({ + iss: 'https://test-123.auth0.com/', + id_token: TEST_ID_TOKEN + }) + ); + }); + + it('calls `tokenVerifier.verify` with the global organization id', async () => { + const auth0 = setup({ organization: 'test_org_123' }); + + await loginWithRedirect(auth0); + + expect(tokenVerifier).toHaveBeenCalledWith( + expect.objectContaining({ + organizationId: 'test_org_123' + }) + ); + }); + + it('calls `tokenVerifier.verify` with the specific organization id', async () => { + const auth0 = setup({ organization: 'test_org_123' }); + + await loginWithRedirect(auth0, { organization: 'test_org_456' }); + + expect(tokenVerifier).toHaveBeenCalledWith( + expect.objectContaining({ + organizationId: 'test_org_456' + }) + ); + }); + + it('saves into cache', async () => { + const auth0 = setup(); + + jest.spyOn(auth0['cache'], 'save'); + + await loginWithRedirect(auth0); + + expect(auth0['cache']['save']).toHaveBeenCalledWith( + expect.objectContaining({ + client_id: TEST_CLIENT_ID, + access_token: TEST_ACCESS_TOKEN, + expires_in: 86400, + audience: 'default', + id_token: TEST_ID_TOKEN, + scope: TEST_SCOPES + }) + ); + }); + + it('saves `auth0.is.authenticated` key in storage', async () => { + const auth0 = setup(); + + await loginWithRedirect(auth0); + + expect(esCookie.set).toHaveBeenCalledWith( + '_legacy_auth0.is.authenticated', + 'true', + { + expires: 1 + } + ); + + expect(esCookie.set).toHaveBeenCalledWith( + 'auth0.is.authenticated', + 'true', + { + expires: 1 + } + ); + }); + + it('saves `auth0.is.authenticated` key in storage for an extended period', async () => { + const auth0 = setup({ + sessionCheckExpiryDays: 2 + }); + + await loginWithRedirect(auth0); + + expect(esCookie.set).toHaveBeenCalledWith( + '_legacy_auth0.is.authenticated', + 'true', + { + expires: 2 + } + ); + expect(esCookie.set).toHaveBeenCalledWith( + 'auth0.is.authenticated', + 'true', + { + expires: 2 + } + ); + }); }); describe('handleRedirectCallback', () => { @@ -755,17 +920,214 @@ describe('Auth0Client', () => { it('should throw an error if the /authorize call redirects with an error param', async () => { const auth0 = setup(); let error; + const appState = { + key: 'property' + }; try { - await loginWithRedirect(auth0, undefined, { - authorize: { - error: 'some-error' + await loginWithRedirect( + auth0, + { appState }, + { + authorize: { + state: 'error-state', + error: 'some-error', + errorDescription: 'some-error-description' + } } - }); + ); } catch (e) { error = e; } expect(error).toBeDefined(); expect(error.error).toBe('some-error'); + expect(error.error_description).toBe('some-error-description'); + expect(error.state).toBe('error-state'); + expect(error.appState).toBe(appState); + }); + + it('should clear the transaction data when the /authorize call redirects with a code param', async () => { + const auth0 = setup(); + + jest.spyOn(auth0['transactionManager'], 'remove'); + + await loginWithRedirect(auth0); + + expect(auth0['transactionManager'].remove).toHaveBeenCalledWith(); + }); + + it('should clear the transaction data when the /authorize call redirects with an error param', async () => { + const auth0 = setup(); + let error; + jest.spyOn(auth0['transactionManager'], 'remove'); + + try { + await loginWithRedirect( + auth0, + {}, + { + authorize: { + error: 'some-error' + } + } + ); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(auth0['transactionManager'].remove).toHaveBeenCalledWith(); + }); + + it('should throw an error if the /authorize call redirects with no params', async () => { + const auth0 = setup(); + let error; + try { + await loginWithRedirect( + auth0, + {}, + { + authorize: { + error: null, + state: null, + code: null + } + } + ); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toBe( + 'There are no query params available for parsing.' + ); + }); + + it('should throw an error if there is no transaction', async () => { + const auth0 = setup(); + let error; + try { + await auth0.handleRedirectCallback('test?foo=bar'); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toBe('Invalid state'); + }); + + it('returns the transactions appState', async () => { + const auth0 = setup(); + const appState = { + key: 'property' + }; + const result = await loginWithRedirect(auth0, { appState }); + expect(result).toBeDefined(); + expect(result.appState).toBe(appState); + }); + + describe('when there is a valid query string in a hash', () => { + it('should throw an error if the /authorize call redirects with an error param', async () => { + const auth0 = setup(); + let error; + const appState = { + key: 'property' + }; + try { + await loginWithRedirect( + auth0, + { appState }, + { + authorize: { + state: 'error-state', + error: 'some-error', + errorDescription: 'some-error-description' + }, + useHash: true + } + ); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.error).toBe('some-error'); + expect(error.error_description).toBe('some-error-description'); + expect(error.state).toBe('error-state'); + expect(error.appState).toBe(appState); + }); + + it('should clear the transaction data when the /authorize call redirects with a code param', async () => { + const auth0 = setup(); + + jest.spyOn(auth0['transactionManager'], 'remove'); + await loginWithRedirect( + auth0, + {}, + { + useHash: true + } + ); + + expect(auth0['transactionManager'].remove).toHaveBeenCalledWith(); + }); + + it('should clear the transaction data when the /authorize call redirects with an error param', async () => { + const auth0 = setup(); + let error; + jest.spyOn(auth0['transactionManager'], 'remove'); + + try { + await loginWithRedirect( + auth0, + {}, + { + authorize: { + error: 'some-error' + }, + useHash: true + } + ); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(auth0['transactionManager'].remove).toHaveBeenCalledWith(); + }); + + it('should throw an error if the /authorize call redirects with no params', async () => { + const auth0 = setup(); + let error; + try { + await loginWithRedirect( + auth0, + {}, + { + authorize: { + state: null, + code: null + }, + useHash: true + } + ); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toBe( + 'There are no query params available for parsing.' + ); + }); + + it('should throw an error if there is no transaction', async () => { + const auth0 = setup(); + let error; + try { + await auth0.handleRedirectCallback('#test?foo=bar'); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toBe('Invalid state'); + }); }); }); diff --git a/__tests__/index.test.ts b/__tests__/index.test.ts index dad824500..3ff16d2c4 100644 --- a/__tests__/index.test.ts +++ b/__tests__/index.test.ts @@ -517,13 +517,6 @@ describe('Auth0', () => { }); describe('handleRedirectCallback()', () => { - it('throws when there is no query string', async () => { - const { auth0 } = await setup(); - await expect(auth0.handleRedirectCallback()).rejects.toThrow( - 'There are no query params available for parsing.' - ); - }); - describe('when there is a valid query string in the url', () => { const localSetup = async ( clientOptions?: Partial @@ -544,163 +537,8 @@ describe('Auth0', () => { result.cache.get.mockReturnValue({ access_token: TEST_ACCESS_TOKEN }); return result; }; - it('calls parseQueryResult correctly', async () => { - const { auth0, utils } = await localSetup(); - await auth0.handleRedirectCallback(); - expect(utils.parseQueryResult).toHaveBeenCalledWith( - `code=${TEST_CODE}&state=${TEST_ENCODED_STATE}` - ); - }); - it('uses `state` from parsed query to get a transaction', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - const queryState = 'the-state'; - utils.parseQueryResult.mockReturnValue({ state: queryState }); - - await auth0.handleRedirectCallback(); - - expect(transactionManager.get).toHaveBeenCalled(); - }); - it('throws error with AuthenticationError', async () => { - const { auth0, utils } = await localSetup(); - const queryResult = { error: 'unauthorized' }; - utils.parseQueryResult.mockReturnValue(queryResult); - - await expect(auth0.handleRedirectCallback()).rejects.toBeInstanceOf( - AuthenticationError - ); - }); - it('throws AuthenticationError with message from error_description', async () => { - const { auth0, utils } = await localSetup(); - const queryResult = { - error: 'unauthorized', - error_description: 'Unauthorized user' - }; - utils.parseQueryResult.mockReturnValue(queryResult); - - await expect(auth0.handleRedirectCallback()).rejects.toThrow( - queryResult.error_description - ); - }); - - it('throws AuthenticationError with state, error, error_description', async () => { - const { auth0, utils } = await localSetup(); - const queryResult = { - error: 'unauthorized', - error_description: 'Unauthorized user', - state: 'abcxyz' - }; - utils.parseQueryResult.mockReturnValue(queryResult); - - let errorThrown: AuthenticationError; - try { - await auth0.handleRedirectCallback(); - } catch (error) { - errorThrown = error; - } - - expect(errorThrown.state).toEqual(queryResult.state); - expect(errorThrown.error).toEqual(queryResult.error); - expect(errorThrown.error_description).toEqual( - queryResult.error_description - ); - }); - - it('throws AuthenticationError and includes the transaction state', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - - const appState = { - key: 'property' - }; - - transactionManager.get.mockReturnValue({ - appState, - nonce: 'foo', - code_verifier: 'bar' - }); - - const queryResult = { - error: 'unauthorized', - error_description: 'Unauthorized user', - state: 'abcxyz' - }; - - utils.parseQueryResult.mockReturnValue(queryResult); - - let errorThrown: AuthenticationError; - - try { - await auth0.handleRedirectCallback(); - } catch (error) { - errorThrown = error; - } - - expect(errorThrown.appState).toEqual(appState); - }); - - it('throws error when there is no transaction', async () => { - const { auth0, transactionManager } = await localSetup(); - transactionManager.get.mockReturnValue(undefined); - - await expect(auth0.handleRedirectCallback()).rejects.toThrow( - 'Invalid state' - ); - }); - it('clears the transaction data when an error occurs', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - const queryResult = { error: 'unauthorized', state: '897dfuksdfuo' }; - utils.parseQueryResult.mockReturnValue(queryResult); - - try { - await auth0.handleRedirectCallback(); - } catch (e) { - expect(transactionManager.remove).toHaveBeenCalledWith(); - } - }); - it('uses `state` from parsed query to remove the transaction', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - const queryState = 'the-state'; - utils.parseQueryResult.mockReturnValue({ state: queryState }); - - await auth0.handleRedirectCallback(); - - expect(transactionManager.remove).toHaveBeenCalled(); - }); - it('calls oauth/token with correct params', async () => { - const { auth0, utils } = await localSetup(); - await auth0.handleRedirectCallback(); - - expect(utils.oauthToken).toHaveBeenCalledWith( - { - audience: 'default', - scope: TEST_SCOPES, - baseUrl: `https://${TEST_DOMAIN}`, - client_id: TEST_CLIENT_ID, - code: TEST_CODE, - code_verifier: TEST_RANDOM_STRING, - grant_type: 'authorization_code' - }, - undefined - ); - }); - - it('calls oauth/token with redirect uri from transaction if set', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - const txn = transactionManager.get.mockReturnValue({ - code_verifier: TEST_RANDOM_STRING, - nonce: TEST_RANDOM_STRING, - audience: 'default', - scope: TEST_SCOPES, - appState: TEST_APP_STATE, - redirect_uri: 'http://localhost' - }); - await auth0.handleRedirectCallback(); - const arg = utils.oauthToken.mock.calls[0][0]; - expect(arg.hasOwnProperty('redirect_uri')).toBeTruthy(); - expect(arg.redirect_uri).toEqual('http://localhost'); - }); - - it('calls oauth/token without redirect uri if not set in transaction', async () => { + xit('calls oauth/token without redirect uri if not set in transaction', async () => { const { auth0, utils, transactionManager } = await localSetup(); const txn = transactionManager.get.mockReturnValue({ code_verifier: TEST_RANDOM_STRING, @@ -713,100 +551,6 @@ describe('Auth0', () => { const arg = utils.oauthToken.mock.calls[0][0]; expect(arg.hasOwnProperty('redirect_uri')).toBeFalsy(); }); - - it('calls `tokenVerifier.verify` with the `id_token` from in the oauth/token response', async () => { - const { auth0, tokenVerifier } = await localSetup(); - - await auth0.handleRedirectCallback(); - - expect(tokenVerifier).toHaveBeenCalledWith({ - id_token: TEST_ID_TOKEN, - nonce: TEST_ENCODED_STATE, - aud: TEST_CLIENT_ID, - iss: `https://${TEST_DOMAIN}/`, - leeway: undefined, - max_age: undefined - }); - }); - - it('calls `tokenVerifier.verify` with the organization ID from in the transaction, if set', async () => { - const { auth0, tokenVerifier, transactionManager } = await localSetup(); - - transactionManager.get.mockReturnValue({ - code_verifier: TEST_RANDOM_STRING, - nonce: TEST_RANDOM_STRING, - audience: 'default', - scope: TEST_SCOPES, - redirect_uri: 'http://localhost', - organizationId: TEST_ORG_ID - }); - - await auth0.handleRedirectCallback(); - - expect(tokenVerifier).toHaveBeenCalledWith({ - id_token: TEST_ID_TOKEN, - nonce: TEST_RANDOM_STRING, - aud: TEST_CLIENT_ID, - iss: `https://${TEST_DOMAIN}/`, - leeway: undefined, - max_age: undefined, - organizationId: TEST_ORG_ID - }); - }); - - it('saves cache', async () => { - const { auth0, cache } = await localSetup(); - - await auth0.handleRedirectCallback(); - - expect(cache.save).toHaveBeenCalledWith({ - client_id: TEST_CLIENT_ID, - access_token: TEST_ACCESS_TOKEN, - audience: 'default', - id_token: TEST_ID_TOKEN, - scope: TEST_SCOPES, - decodedToken: { - claims: { sub: TEST_USER_ID, aud: TEST_CLIENT_ID }, - user: { sub: TEST_USER_ID } - } - }); - }); - it('saves `auth0.is.authenticated` key in storage', async () => { - const { auth0, cookieStorage } = await localSetup(); - - await auth0.handleRedirectCallback(); - - expect(cookieStorage.save).toHaveBeenCalledWith( - 'auth0.is.authenticated', - true, - { - daysUntilExpire: 1 - } - ); - }); - it('saves `auth0.is.authenticated` key in storage for an extended period', async () => { - const { auth0, cookieStorage } = await localSetup({ - sessionCheckExpiryDays: 2 - }); - - await auth0.handleRedirectCallback(); - - expect(cookieStorage.save).toHaveBeenCalledWith( - 'auth0.is.authenticated', - true, - { - daysUntilExpire: 2 - } - ); - }); - it('returns the transactions appState', async () => { - const { auth0 } = await localSetup(); - const response = await auth0.handleRedirectCallback(); - - expect(response).toEqual({ - appState: TEST_APP_STATE - }); - }); }); describe('when there is a valid query string in a hash', () => { const localSetup = async ( @@ -829,119 +573,7 @@ describe('Auth0', () => { result.cache.get.mockReturnValue({ access_token: TEST_ACCESS_TOKEN }); return result; }; - it('calls parseQueryResult correctly', async () => { - const { auth0, utils } = await localSetup(); - await auth0.handleRedirectCallback(); - expect(utils.parseQueryResult).toHaveBeenCalledWith( - `code=${TEST_CODE}&state=${TEST_ENCODED_STATE}` - ); - }); - it('calls parseQueryResult with a passed URL', async () => { - const { auth0, utils } = await localSetup(); - const customUrl = `https://test.auth0.com?code=${TEST_CODE}&state=${TEST_ENCODED_STATE}`; - await auth0.handleRedirectCallback(customUrl); - expect(utils.parseQueryResult).toHaveBeenCalledWith( - `code=${TEST_CODE}&state=${TEST_ENCODED_STATE}` - ); - }); - it('uses `state` from parsed query to get a transaction', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - const queryState = 'the-state'; - utils.parseQueryResult.mockReturnValue({ state: queryState }); - - await auth0.handleRedirectCallback(); - - expect(transactionManager.get).toHaveBeenCalled(); - }); - it('throws error with AuthenticationError', async () => { - const { auth0, utils } = await localSetup(); - const queryResult = { error: 'unauthorized' }; - utils.parseQueryResult.mockReturnValue(queryResult); - - await expect(auth0.handleRedirectCallback()).rejects.toBeInstanceOf( - AuthenticationError - ); - }); - it('throws AuthenticationError with message from error_description', async () => { - const { auth0, utils } = await localSetup(); - const queryResult = { - error: 'unauthorized', - error_description: 'Unauthorized user' - }; - utils.parseQueryResult.mockReturnValue(queryResult); - - await expect(auth0.handleRedirectCallback()).rejects.toThrow( - queryResult.error_description - ); - }); - it('throws AuthenticationError with state, error, error_description', async () => { - const { auth0, utils } = await localSetup(); - const queryResult = { - error: 'unauthorized', - error_description: 'Unauthorized user', - state: 'abcxyz' - }; - utils.parseQueryResult.mockReturnValue(queryResult); - - let errorThrown: AuthenticationError; - try { - await auth0.handleRedirectCallback(); - } catch (error) { - errorThrown = error; - } - - expect(errorThrown.state).toEqual(queryResult.state); - expect(errorThrown.error).toEqual(queryResult.error); - expect(errorThrown.error_description).toEqual( - queryResult.error_description - ); - }); - it('clears the transaction data when an error occurs', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - const queryResult = { error: 'unauthorized', state: '897dfuksdfuo' }; - utils.parseQueryResult.mockReturnValue(queryResult); - - try { - await auth0.handleRedirectCallback(); - } catch (e) { - expect(transactionManager.remove).toHaveBeenCalledWith(); - } - }); - it('throws error when there is no transaction', async () => { - const { auth0, transactionManager } = await localSetup(); - transactionManager.get.mockReturnValue(undefined); - - await expect(auth0.handleRedirectCallback()).rejects.toThrow( - 'Invalid state' - ); - }); - it('uses `state` from parsed query to remove the transaction', async () => { - const { auth0, utils, transactionManager } = await localSetup(); - const queryState = 'the-state'; - utils.parseQueryResult.mockReturnValue({ state: queryState }); - - await auth0.handleRedirectCallback(); - - expect(transactionManager.remove).toHaveBeenCalled(); - }); - it('calls oauth/token with correct params', async () => { - const { auth0, utils } = await localSetup(); - await auth0.handleRedirectCallback(); - - expect(utils.oauthToken).toHaveBeenCalledWith( - { - audience: 'default', - scope: TEST_SCOPES, - baseUrl: `https://${TEST_DOMAIN}`, - client_id: TEST_CLIENT_ID, - code: TEST_CODE, - code_verifier: TEST_RANDOM_STRING, - grant_type: 'authorization_code' - }, - undefined - ); - }); it('calls `tokenVerifier.verify` with the `id_token` from in the oauth/token response', async () => { const { auth0, tokenVerifier } = await localSetup();