Skip to content

Commit

Permalink
[SDK-2106] Memoize auth methods (#150)
Browse files Browse the repository at this point in the history
* Memoize auth methods

* fix import
  • Loading branch information
adamjmcgrath authored Oct 30, 2020
1 parent c3e50a1 commit c1fc3ca
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 52 deletions.
12 changes: 12 additions & 0 deletions __tests__/auth-provider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -457,4 +457,16 @@ describe('Auth0Provider', () => {
__raw: '__test_raw_token__',
});
});

it('should memoize the getIdTokenClaims method', async () => {
const wrapper = createWrapper();
const { waitForNextUpdate, result, rerender } = renderHook(
() => useContext(Auth0Context),
{ wrapper }
);
await waitForNextUpdate();
const memoized = result.current.getIdTokenClaims;
rerender();
expect(result.current.getIdTokenClaims).toBe(memoized);
});
});
125 changes: 73 additions & 52 deletions src/auth0-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useReducer, useState } from 'react';
import React, { useCallback, useEffect, useReducer, useState } from 'react';
import {
Auth0Client,
Auth0ClientOptions,
Expand All @@ -10,6 +10,7 @@ import {
RedirectLoginOptions as Auth0RedirectLoginOptions,
GetTokenWithPopupOptions,
GetTokenSilentlyOptions,
GetIdTokenClaimsOptions,
} from '@auth0/auth0-spa-js';
import Auth0Context, { RedirectLoginOptions } from './auth0-context';
import { hasAuthParams, loginError, tokenError } from './utils';
Expand Down Expand Up @@ -225,67 +226,87 @@ const Auth0Provider = (opts: Auth0ProviderOptions): JSX.Element => {
})();
}, [client, onRedirectCallback, skipRedirectCallback]);

const loginWithPopup = async (
options?: PopupLoginOptions,
config?: PopupConfigOptions
): Promise<void> => {
dispatch({ type: 'LOGIN_POPUP_STARTED' });
try {
await client.loginWithPopup(options, config);
} catch (error) {
dispatch({ type: 'ERROR', error: loginError(error) });
return;
}
const user = await client.getUser();
dispatch({ type: 'LOGIN_POPUP_COMPLETE', user });
};
const loginWithRedirect = useCallback(
(opts?: Auth0RedirectLoginOptions): Promise<void> =>
client.loginWithRedirect(toAuth0LoginRedirectOptions(opts)),
[client]
);

const logout = (opts: LogoutOptions = {}): void => {
client.logout(opts);
if (opts.localOnly) {
dispatch({ type: 'LOGOUT' });
}
};
const loginWithPopup = useCallback(
async (
options?: PopupLoginOptions,
config?: PopupConfigOptions
): Promise<void> => {
dispatch({ type: 'LOGIN_POPUP_STARTED' });
try {
await client.loginWithPopup(options, config);
} catch (error) {
dispatch({ type: 'ERROR', error: loginError(error) });
return;
}
const user = await client.getUser();
dispatch({ type: 'LOGIN_POPUP_COMPLETE', user });
},
[client]
);

const getAccessTokenSilently = async (
opts?: GetTokenSilentlyOptions
): Promise<string> => {
let token;
try {
token = await client.getTokenSilently(opts);
} catch (error) {
throw tokenError(error);
}
const user = await client.getUser();
dispatch({ type: 'GET_TOKEN_COMPLETE', user });
return token;
};
const logout = useCallback(
(opts: LogoutOptions = {}): void => {
client.logout(opts);
if (opts.localOnly) {
dispatch({ type: 'LOGOUT' });
}
},
[client]
);

const getAccessTokenWithPopup = async (
opts?: GetTokenWithPopupOptions,
config?: PopupConfigOptions
): Promise<string> => {
let token;
try {
token = await client.getTokenWithPopup(opts, config);
} catch (error) {
throw tokenError(error);
}
const user = await client.getUser();
dispatch({ type: 'GET_TOKEN_COMPLETE', user });
return token;
};
const getAccessTokenSilently = useCallback(
async (opts?: GetTokenSilentlyOptions): Promise<string> => {
let token;
try {
token = await client.getTokenSilently(opts);
} catch (error) {
throw tokenError(error);
}
const user = await client.getUser();
dispatch({ type: 'GET_TOKEN_COMPLETE', user });
return token;
},
[client]
);

const getAccessTokenWithPopup = useCallback(
async (
opts?: GetTokenWithPopupOptions,
config?: PopupConfigOptions
): Promise<string> => {
let token;
try {
token = await client.getTokenWithPopup(opts, config);
} catch (error) {
throw tokenError(error);
}
const user = await client.getUser();
dispatch({ type: 'GET_TOKEN_COMPLETE', user });
return token;
},
[client]
);

const getIdTokenClaims = useCallback(
(opts?: GetIdTokenClaimsOptions): Promise<IdToken> =>
client.getIdTokenClaims(opts),
[client]
);

return (
<Auth0Context.Provider
value={{
...state,
getAccessTokenSilently,
getAccessTokenWithPopup,
getIdTokenClaims: (opts): Promise<IdToken> =>
client.getIdTokenClaims(opts),
loginWithRedirect: (opts): Promise<void> =>
client.loginWithRedirect(toAuth0LoginRedirectOptions(opts)),
getIdTokenClaims,
loginWithRedirect,
loginWithPopup,
logout,
}}
Expand Down

0 comments on commit c1fc3ca

Please sign in to comment.