Skip to content

Instantly share code, notes, and snippets.

@mrnkr
Created February 10, 2019 21:20
Show Gist options
  • Save mrnkr/663977a2cf81687f4bbe5e704eaa7137 to your computer and use it in GitHub Desktop.
Save mrnkr/663977a2cf81687f4bbe5e704eaa7137 to your computer and use it in GitHub Desktop.
Redux middleware to exchange a refresh token prior to any request if the access token is expired
async function refresh(dispatch: Dispatch, getState: () => MyState): Promise<void> {
const { auth: { authenticated, refresh_token: refresh } } = getState();
if (!authenticated)
return;
try {
const { access_token, refresh_token, token_type } = await (async () => {
const res = await fetch(`${baseUrl}/oauth2/token`, {
method: 'POST',
headers: {
"Authorization": `Basic ${btoa(`${client.name}:${client.secret}`)}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"grant_type": "refresh_token",
"refresh_token": refresh
})
});
return res.json();
})();
const token_expiration = new Date(Date.now() + TOKEN_DURATION_MINUTES * 60000).toISOString();
dispatch({ type: AuthActions.REFRESH, payload: { access_token, refresh_token, token_type, token_expiration } });
} catch (err) {
dispatch({ type: AuthActions.ERROR });
}
}
// Redux middleware to keep tokens alive :D
// Apply before thunk if using thunk 👈
export const assertAuth: Middleware<Dispatch, MyState> =
({ dispatch, getState }) => next => async action => {
const { auth: { authenticated, token_expiration } } = getState();
// Prevent unnecessary calls and infinite loops
if (!authenticated || action.type === AuthActions.REFRESH)
return next(action);
const now = new Date();
const expiration = new Date(token_expiration as string);
const isExpired = now > expiration;
if (isExpired)
await refresh(dispatch, getState);
return next(action);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment