Skip to content

Instantly share code, notes, and snippets.

@JonCatmull
Last active June 24, 2020 15:51
Show Gist options
  • Save JonCatmull/22b0537126f5d1b056b68b4eeab2578a to your computer and use it in GitHub Desktop.
Save JonCatmull/22b0537126f5d1b056b68b4eeab2578a to your computer and use it in GitHub Desktop.
RxJs operator to reload a JWT when it expires
import { MonoTypeOperatorFunction, BehaviorSubject, Observable } from 'rxjs';
import { switchMapTo, tap, shareReplay } from 'rxjs/operators';
import JwtDecode from 'jwt-decode';
/**
* Replays a JWT observable stream. If the JWT's exp passes then the source observable
* will be re triggered automatically to get a new token.
* This replays last value so the token will only update when it expires or because of an
* upstream event, regardless of new subscriptions. Look up shareReplay() for more details.
* @requires exp Token's must contain a exp to be used with this.
*/
export default function autoReloadJwt(): MonoTypeOperatorFunction<string> {
return (input$): Observable<string> => {
// subject which we call next on to trigger source observable which requests a token from api
// behaviour subjects always have a value so it will emit immidiately when subscribed to.
const refreshSubject = new BehaviorSubject<void>(undefined);
let timeout: number;
return refreshSubject.pipe(
switchMapTo(input$),
tap(jwt => {
// clear old timeout incase new token was not the rsult of the timeout
clearTimeout(timeout);
// set timeout to trigger refresh subject when token expires
const { exp } = JwtDecode<{ exp: number }>(jwt);
timeout = window.setTimeout(() => {
refreshSubject.next();
}, exp * 1000 - new Date().getTime());
}),
shareReplay(1)
);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment