fix(ui): silent-callback redirect issue fix (#7297)

* fix(ui): silent-callback redirect issue fix

* address comments
This commit is contained in:
Chirag Madlani 2022-09-07 16:55:25 +05:30 committed by GitHub
parent 422f59d9e6
commit 1a9a67b087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 30 deletions

View File

@ -17,7 +17,6 @@ import { MsalProvider } from '@azure/msal-react';
import { LoginCallback } from '@okta/okta-react';
import { AxiosError } from 'axios';
import { CookieStorage } from 'cookie-storage';
import jwtDecode, { JwtPayload } from 'jwt-decode';
import { isEmpty, isNil } from 'lodash';
import { observer } from 'mobx-react';
import React, {
@ -51,6 +50,7 @@ import { AuthTypes } from '../../enums/signin.enum';
import { User } from '../../generated/entity/teams/user';
import jsonData from '../../jsons/en';
import {
extractDetailsFromToken,
getAuthConfig,
getNameFromEmail,
getUrlPathnameExpiry,
@ -109,10 +109,11 @@ export const AuthProvider = ({
authenticatorRef.current?.invokeLogin();
};
const onLogoutHandler = () => {
const onLogoutHandler = useCallback(() => {
clearTimeout(timeoutId);
authenticatorRef.current?.invokeLogout();
setLoading(false);
};
}, [timeoutId]);
const onRenewIdTokenHandler = () => {
return authenticatorRef.current?.renewIdToken();
@ -292,31 +293,21 @@ export const AuthProvider = ({
* This method will be call upon successful signIn
*/
const startTokenExpiryTimer = () => {
const token: string | void = localStorage.getItem(oidcTokenKey) || '';
// If token is not present do nothing
if (token) {
try {
// Extract expiry
const { exp } = jwtDecode<JwtPayload>(token);
if (exp && exp * 1000 > Date.now()) {
// Check if token isn't expired yet
const diff = exp * 1000 - Date.now(); /* Convert to MS */
// Extract expiry
const { exp, isExpired, diff, timeoutExpiry } = extractDetailsFromToken();
// Have 50s buffer before start trying for silent signIn
// If token is about to expire then start silentSignIn
// else just set timer to try for silentSignIn before token expires
if (diff > 50000) {
const timerId = setTimeout(() => {
trySilentSignIn();
}, diff);
setTimeoutId(Number(timerId));
} else {
trySilentSignIn();
}
}
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error parsing id token.', error);
if (!isExpired && exp && diff && timeoutExpiry) {
// Have 2m buffer before start trying for silent signIn
// If token is about to expire then start silentSignIn
// else just set timer to try for silentSignIn before token expires
if (diff > 120000) {
clearTimeout(timeoutId);
const timerId = setTimeout(() => {
trySilentSignIn();
}, timeoutExpiry);
setTimeoutId(Number(timerId));
} else {
trySilentSignIn();
}
}
};

View File

@ -21,7 +21,8 @@ export const useAuth = (pathname = '') => {
const isAuthenticatedRoute =
pathname !== ROUTES.SIGNUP &&
pathname !== ROUTES.SIGNIN &&
pathname !== ROUTES.CALLBACK;
pathname !== ROUTES.CALLBACK &&
pathname !== ROUTES.SILENT_CALLBACK;
const isTourRoute = pathname === ROUTES.TOUR;
return {

View File

@ -18,15 +18,19 @@ import {
PopupRequest,
PublicClientApplication,
} from '@azure/msal-browser';
import jwtDecode, { JwtPayload } from 'jwt-decode';
import { isNil } from 'lodash';
import { WebStorageStateStore } from 'oidc-client';
import { ROUTES } from '../constants/constants';
import { oidcTokenKey, ROUTES } from '../constants/constants';
import { validEmailRegEx } from '../constants/regex.constants';
import { AuthTypes } from '../enums/signin.enum';
import { isDev } from './EnvironmentUtils';
export let msalInstance: IPublicClientApplication;
const DATE_NOW = Date.now();
const EXPIRY_THRESHOLD_MILLES = 2 * 60 * 100;
export const getOidcExpiry = () => {
return new Date(Date.now() + 60 * 60 * 24 * 1000);
};
@ -184,7 +188,8 @@ export const isProtectedRoute = (pathname: string) => {
return (
pathname !== ROUTES.SIGNUP &&
pathname !== ROUTES.SIGNIN &&
pathname !== ROUTES.CALLBACK
pathname !== ROUTES.CALLBACK &&
pathname !== ROUTES.SILENT_CALLBACK
);
};
@ -195,3 +200,38 @@ export const isTourRoute = (pathname: string) => {
export const getUrlPathnameExpiry = () => {
return new Date(Date.now() + 60 * 60 * 1000);
};
/**
* @exp expiry of token
* @isExpired wether token is already expired or not
* @diff Difference between token expiry & current time in ms
* @timeoutExpiry time in ms for try to silent sign-in
* @returns exp, isExpired, diff, timeoutExpiry
*/
export const extractDetailsFromToken = () => {
const token = localStorage.getItem(oidcTokenKey) || '';
try {
const { exp } = jwtDecode<JwtPayload>(token);
const diff = exp && exp * 1000 - DATE_NOW;
const timeoutExpiry = diff && diff - EXPIRY_THRESHOLD_MILLES;
return {
exp,
isExpired: exp && DATE_NOW >= exp * 1000,
diff,
timeoutExpiry,
};
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error parsing id token.', error);
}
return {
exp: 0,
isExpired: true,
diff: 0,
timeoutExpiry: 0,
};
};