Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1495 from navikt/handtere-feil-ved-refresh
Browse files Browse the repository at this point in the history
Handtere utloggingsvarsel i tabs/vinduer kombinert med token refresh
  • Loading branch information
terjeofnorway authored Oct 5, 2023
2 parents ff4be44 + 6e1cae0 commit a4940a2
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 18 deletions.
11 changes: 8 additions & 3 deletions src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ export const fornyInnloggingFetch = (environment: Environment): Promise<SessionD

return fetchToJson(refreshUrl, {
credentials: 'include',
}).then((result: any) => {
return adaptFulfilledSessionDataFromAPI(result);
});
})
.then((result: any) => {
return adaptFulfilledSessionDataFromAPI(result);
})
.catch((e) => {
window.dispatchEvent(new Event('INVALID_SESSION'));
throw new Error(`Error refreshing session [error: ${e}]`);
});
};

export const hentVarslerFetch = (VARSEL_API_URL: string): Promise<varselinnboksData> => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
display: flex;
flex-direction: column;
padding: 1rem;
align-items: center;
align-items: flex-start;
box-shadow: var(--a-shadow-large);
justify-content: center;
opacity: 0;
Expand Down
53 changes: 44 additions & 9 deletions src/komponenter/header/logoutWarning/LogoutWarning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ import { LangKey } from 'tekster/ledetekster';
import styles from './LogoutWarning.module.scss';

export const LogoutWarning = () => {
const { refreshTokenHandler, logoutHandler, isTokenExpiring, isSessionExpiring, secondsToSessionExpires } =
useLoginStatus();
const {
refreshTokenHandler,
loginHandler,
logoutHandler,
isTokenExpiring,
isSessionExpiring,
secondsToSessionExpires,
hasAuthError,
} = useLoginStatus();
const [isOpen, setIsOpen] = React.useState(false);
const { language } = useSelector((state: AppState) => state.language);

Expand All @@ -34,8 +41,24 @@ export const LogoutWarning = () => {
return null;
}

const titleId: LangKey = isSessionExpiring ? 'snart-session-logget-ut-tittel' : 'snart-token-logget-ut-tittel';
const textBodyId: LangKey = isSessionExpiring ? 'snart-session-logget-ut-body' : 'snart-token-logget-ut-body';
const getTitleId = () => {
if (hasAuthError) {
return 'token-feilet-tittel';
}

return isSessionExpiring ? 'snart-session-logget-ut-tittel' : 'snart-token-logget-ut-tittel';
};

const getBodyId = () => {
if (hasAuthError) {
return 'token-feilet-body';
}

return isSessionExpiring ? 'snart-session-logget-ut-body' : 'snart-token-logget-ut-body';
};

const titleId: LangKey = getTitleId();
const textBodyId: LangKey = getBodyId();

const minutesToSessionEnd = Math.ceil(secondsToSessionExpires / 60);

Expand All @@ -53,19 +76,31 @@ export const LogoutWarning = () => {
<Modal.Body className={styles.content}>
<BodyLong spacing>{finnTekst(textBodyId, language)}</BodyLong>
<div className={styles.buttonWrapper}>
{isSessionExpiring && (
{hasAuthError && (
<>
<Button className={styles.confirm} onClick={loginHandler}>
{finnTekst('logg-inn-pa-nytt-knapp', language)}
</Button>
<Button className={styles.confirm} onClick={logoutHandler} variant="tertiary">
{finnTekst('token-feilet-avbryt', language)}
</Button>
</>
)}
{!hasAuthError && isSessionExpiring && (
<Button className={styles.confirm} onClick={onCloseHandler}>
{finnTekst('ok', language)}
</Button>
)}
{!isSessionExpiring && isTokenExpiring && (
{!hasAuthError && !isSessionExpiring && isTokenExpiring && (
<Button className={styles.confirm} onClick={refreshTokenHandler}>
{finnTekst('svarknapp-ja', language)}
</Button>
)}
<Button className={styles.logout} onClick={logoutHandler} variant="tertiary">
{finnTekst('logg-ut-knapp', language)}
</Button>
{!hasAuthError && (
<Button className={styles.logout} onClick={logoutHandler} variant="tertiary">
{finnTekst('logg-ut-knapp', language)}
</Button>
)}
</div>
</Modal.Body>
</Modal>
Expand Down
12 changes: 12 additions & 0 deletions src/tekster/ledetekster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export const ledetekster = {
'logg-inn-knapp': 'Logg inn',
'logg-inn-knapp-en': 'Log in',
'logg-inn-knapp-se': 'Sisačáliheapmi',
'logg-inn-pa-nytt-knapp': 'Logg inn på nytt',
'logg-inn-pa-nytt-knapp-en': 'Log in again',
'logg-inn-pa-nytt-knapp-se': 'Logg inn på nytt',
'logg-ut-knapp': 'Logg ut',
'logg-ut-knapp-en': 'Log out',
'logg-ut-knapp-se': 'Olggosčáliheapmi',
Expand All @@ -59,6 +62,15 @@ export const ledetekster = {
'snart-session-logget-ut-body': 'Avslutt det du jobber med og logg inn igjen.',
'snart-session-logget-ut-body-en': 'Please wrap up what you are doing and log in again.',
'snart-session-logget-ut-body-se': 'Avslutt det du jobber med og logg inn igjen.',
'token-feilet-tittel': 'Det har skjedd en feil',
'token-feilet-tittel-en': 'An error has happened',
'token-feilet-tittel-se': 'Det har skjedd en feil',
'token-feilet-body': 'Forsøket på å forlenge innloggingen din feilet, vi beklager.',
'token-feilet-body-en': 'An attempt to extend your login period failed, we apologize.',
'token-feilet-body-se': 'Forsøket på å forlenge innloggingen din feilet, vi beklager.',
'token-feilet-avbryt': `Avbryt`,
'token-feilet-avbryt-en': `Cancel`,
'token-feilet-avbryt-se': `Avbryt`,
ok: 'OK',
'ok-en': 'OK',
'ok-se': 'OK',
Expand Down
36 changes: 31 additions & 5 deletions src/utils/hooks/useLoginStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@ import { useEffect, useRef, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { AppState } from 'store/reducers';
import { hentInnloggingsstatus, fornyInnlogging } from 'store/reducers/innloggingsstatus-duck';
import { getLogOutUrl } from 'utils/login';
import { getLogOutUrl, getLoginUrl } from 'utils/login';
import { useLoginDebug } from './useLoginDebug';

const stateSelector = (state: AppState) => ({
innloggetStatus: state.innloggingsstatus.data,
environment: state.environment,
arbeidsflate: state.arbeidsflate.status,
});

let timeoutId: NodeJS.Timeout | null = null;

export const useLoginStatus = () => {
const dispatch = useDispatch();
const { innloggetStatus, environment } = useSelector(stateSelector);
const { innloggetStatus, environment, arbeidsflate } = useSelector(stateSelector);
const [isTokenExpiring, setIsTokenExpiring] = useState<boolean | null>(null);
const [isSessionExpiring, setIsSessionExpiring] = useState<boolean | null>(null);
const [hasAuthError, setHasAuthError] = useState<boolean>(false);
const [secondsToSessionExpires, setSecondsToSessionExpires] = useState<number>(0);
useLoginDebug();

Expand All @@ -25,6 +27,12 @@ export const useLoginStatus = () => {
const innloggetStatusRef = useRef(innloggetStatus);
innloggetStatusRef.current = innloggetStatus;

useEffect(() => {
window.addEventListener('INVALID_SESSION', () => {
setHasAuthError(true);
});
}, []);

const getExpirationInSeconds = ({ session, token }: { session: string | null; token: string | null }) => {
if (!session || !token) return { secondsToTokenExpires: null, secondsToSessionExpires: null };

Expand Down Expand Up @@ -75,7 +83,11 @@ export const useLoginStatus = () => {
window.location.href = getLogOutUrl(environment);
};

const onVisibilityChange = () => {
const loginHandler = () => {
window.location.href = getLoginUrl(environment, arbeidsflate);
};

const onWindowVisibility = () => {
if (document.visibilityState === 'visible') {
checkLoginAndRepeat();
hentInnloggingsstatus(environment)(dispatch);
Expand All @@ -84,8 +96,22 @@ export const useLoginStatus = () => {

useEffect(() => {
checkLoginAndRepeat();
window.addEventListener('visibilitychange', onVisibilityChange);
window.addEventListener('visibilitychange', onWindowVisibility);
window.addEventListener('focus', onWindowVisibility);

return () => {
window.removeEventListener('visibilitychange', onWindowVisibility);
window.removeEventListener('focus', onWindowVisibility);
};
}, []);

return { isTokenExpiring, isSessionExpiring, refreshTokenHandler, logoutHandler, secondsToSessionExpires };
return {
isTokenExpiring,
isSessionExpiring,
refreshTokenHandler,
logoutHandler,
loginHandler,
secondsToSessionExpires,
hasAuthError,
};
};

0 comments on commit a4940a2

Please sign in to comment.