Skip to content

Commit

Permalink
feat(ui): support refresh with multi tabs open (#17782)
Browse files Browse the repository at this point in the history
* feat(ui): support refresh with multi tabs open

* address comments

* fix clientType error

* fix unit tests

* add version miss match alert for seamless experience

* update variable values

* use custom hook for location

* patch DataInsight app before running it

* fix addRoldeAndAssignToUser flaky test failure
  • Loading branch information
chirag-madlani committed Sep 13, 2024
1 parent 1fdb667 commit 17744f4
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ test.describe.serial('Add role and assign it to the user', () => {
test('Verify assigned role to new user', async ({ page }) => {
await settingClick(page, GlobalSettingOptions.USERS);

await page.waitForSelector('[data-testid="loader"]', { state: 'hidden' });
const searchUser = page.waitForResponse(
`/api/v1/search/query?q=*${encodeURIComponent(userDisplayName)}*`
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,51 @@ setup(

await table.create(apiContext);

apiContext.patch(`/api/v1/tables/${table.entityResponseData?.id ?? ''}`, {
await apiContext.patch(
`/api/v1/tables/${table.entityResponseData?.id ?? ''}`,
{
data: [
{
op: 'add',
path: '/tags/0',
value: {
name: 'Tier2',
tagFQN: 'Tier.Tier2',
labelType: 'Manual',
state: 'Confirmed',
},
},
],
headers: {
'Content-Type': 'application/json-patch+json',
},
}
);

await apiContext.patch(`/api/v1/apps/trigger/DataInsightsApplication`, {
data: [
{
op: 'add',
path: '/tags/0',
value: {
name: 'Tier2',
tagFQN: 'Tier.Tier2',
labelType: 'Manual',
state: 'Confirmed',
},
op: 'remove',
path: '/appConfiguration/backfillConfiguration/startDate',
},
{
op: 'remove',
path: '/appConfiguration/backfillConfiguration/endDate',
},
{
op: 'replace',
path: '/batchSize',
value: 1000,
},
{
op: 'replace',
path: '/recreateDataAssetsIndex',
value: false,
},
{
op: 'replace',
path: '/backfillConfiguration/enabled',
value: false,
},
],
headers: {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import React, {
forwardRef,
Fragment,
ReactNode,
useCallback,
useImperativeHandle,
} from 'react';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -45,34 +46,33 @@ const BasicAuthenticator = forwardRef(
isApplicationLoading,
} = useApplicationStore();

const handleSilentSignIn = async (): Promise<AccessTokenResponse> => {
const refreshToken = getRefreshToken();
const handleSilentSignIn =
useCallback(async (): Promise<AccessTokenResponse> => {
const refreshToken = getRefreshToken();

if (
authConfig?.provider !== AuthProvider.Basic &&
authConfig?.provider !== AuthProvider.LDAP
) {
Promise.reject(t('message.authProvider-is-not-basic'));
}
if (
authConfig?.provider !== AuthProvider.Basic &&
authConfig?.provider !== AuthProvider.LDAP
) {
Promise.reject(t('message.authProvider-is-not-basic'));
}

const response = await getAccessTokenOnExpiry({
refreshToken: refreshToken as string,
});
const response = await getAccessTokenOnExpiry({
refreshToken: refreshToken as string,
});

setRefreshToken(response.refreshToken);
setOidcToken(response.accessToken);
setRefreshToken(response.refreshToken);
setOidcToken(response.accessToken);

return Promise.resolve(response);
};
return Promise.resolve(response);
}, [authConfig, getRefreshToken, setOidcToken, setRefreshToken, t]);

useImperativeHandle(ref, () => ({
invokeLogout() {
handleLogout();
setIsAuthenticated(false);
},
renewIdToken() {
return handleSilentSignIn();
},
renewIdToken: handleSilentSignIn,
}));

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const GenericAuthenticator = forwardRef(
const resp = await renewToken();
setOidcToken(resp.accessToken);

return Promise.resolve(resp);
return resp;
};

useImperativeHandle(ref, () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ const MsalAuthenticator = forwardRef<AuthenticatorRef, Props>(
}
};

const renewIdToken = async () => {
const user = await fetchIdToken();

return user.id_token;
};

useEffect(() => {
const oidcUserToken = getOidcToken();
if (
Expand All @@ -177,23 +183,9 @@ const MsalAuthenticator = forwardRef<AuthenticatorRef, Props>(
}, [inProgress, accounts, instance, account]);

useImperativeHandle(ref, () => ({
invokeLogin() {
login();
},
invokeLogout() {
logout();
},
renewIdToken(): Promise<string> {
return new Promise((resolve, reject) => {
fetchIdToken()
.then((user) => {
resolve(user.id_token);
})
.catch((e) => {
reject(e);
});
});
},
invokeLogin: login,
invokeLogout: logout,
renewIdToken: renewIdToken,
}));

return <Fragment>{children}</Fragment>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,9 @@ const OidcAuthenticator = forwardRef<AuthenticatorRef, Props>(
};

useImperativeHandle(ref, () => ({
invokeLogin() {
login();
},
invokeLogout() {
logout();
},
renewIdToken() {
return signInSilently();
},
invokeLogin: login,
invokeLogout: logout,
renewIdToken: signInSilently,
}));

const AppWithAuth = getAuthenticator(childComponentType, userManager);
Expand Down Expand Up @@ -167,6 +161,7 @@ const OidcAuthenticator = forwardRef<AuthenticatorRef, Props>(
// eslint-disable-next-line no-console
console.error(error);

onLogoutSuccess();
history.push(ROUTES.SIGNIN);
}}
onSuccess={(user) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,20 @@ const OktaAuthenticator = forwardRef<AuthenticatorRef, Props>(
onLogoutSuccess();
};

useImperativeHandle(ref, () => ({
invokeLogin() {
login();
},
invokeLogout() {
logout();
},
async renewIdToken() {
const renewToken = await oktaAuth.token.renewTokens();
oktaAuth.tokenManager.setTokens(renewToken);
const newToken =
renewToken?.idToken?.idToken ?? oktaAuth.getIdToken() ?? '';
setOidcToken(newToken);
const renewToken = async () => {
const renewToken = await oktaAuth.token.renewTokens();
oktaAuth.tokenManager.setTokens(renewToken);
const newToken =
renewToken?.idToken?.idToken ?? oktaAuth.getIdToken() ?? '';
setOidcToken(newToken);

return Promise.resolve(newToken);
};

return Promise.resolve(newToken);
},
useImperativeHandle(ref, () => ({
invokeLogin: login,
invokeLogout: logout,
renewIdToken: renewToken,
}));

return <Fragment>{children}</Fragment>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,9 @@ const SamlAuthenticator = forwardRef<AuthenticatorRef, Props>(
};

useImperativeHandle(ref, () => ({
invokeLogin() {
login();
},
invokeLogout() {
logout();
},
async renewIdToken() {
return handleSilentSignIn();
},
invokeLogin: login,
invokeLogout: logout,
renewIdToken: handleSilentSignIn,
}));

return <Fragment>{children}</Fragment>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {
fetchAuthorizerConfig,
} from '../../../rest/miscAPI';
import { getLoggedInUser, updateUserDetail } from '../../../rest/userAPI';
import TokenService from '../../../utils/Auth/TokenService/TokenServiceUtil';
import {
extractDetailsFromToken,
getAuthConfig,
Expand Down Expand Up @@ -140,6 +141,7 @@ export const AuthProvider = ({
setApplicationLoading,
} = useApplicationStore();
const { updateDomains, updateDomainLoading } = useDomainStore();
const tokenService = useRef<TokenService>();

const location = useCustomLocation();
const history = useHistory();
Expand Down Expand Up @@ -183,9 +185,13 @@ export const AuthProvider = ({
setApplicationLoading(false);
}, [timeoutId]);

const onRenewIdTokenHandler = () => {
return authenticatorRef.current?.renewIdToken();
};
useEffect(() => {
if (authenticatorRef.current?.renewIdToken) {
tokenService.current = new TokenService(
authenticatorRef.current?.renewIdToken
);
}
}, [authenticatorRef.current?.renewIdToken]);

const fetchDomainList = useCallback(async () => {
try {
Expand Down Expand Up @@ -292,8 +298,20 @@ export const AuthProvider = ({
*/
const renewIdToken = async () => {
try {
const onRenewIdTokenHandlerPromise = onRenewIdTokenHandler();
onRenewIdTokenHandlerPromise && (await onRenewIdTokenHandlerPromise);
if (!tokenService.current?.isTokenUpdateInProgress()) {
await tokenService.current?.refreshToken();
} else {
// wait for renewal to complete
const wait = new Promise((resolve) => {
setTimeout(() => {
return resolve(true);
}, 500);
});
await wait;

// should have updated token after renewal
return getOidcToken();
}
} catch (error) {
// eslint-disable-next-line no-console
console.error(
Expand Down Expand Up @@ -353,8 +371,7 @@ export const AuthProvider = ({
const startTokenExpiryTimer = () => {
// Extract expiry
const { isExpired, timeoutExpiry } = extractDetailsFromToken(
getOidcToken(),
clientType
getOidcToken()
);
const refreshToken = getRefreshToken();

Expand Down
Loading

0 comments on commit 17744f4

Please sign in to comment.