Skip to content

Commit

Permalink
Add loggout page, implement legacy login/out redirect
Browse files Browse the repository at this point in the history
  • Loading branch information
dauglyon committed Aug 1, 2024
1 parent c7a8039 commit 81b6d26
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 44 deletions.
2 changes: 2 additions & 0 deletions src/app/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import ORCIDLinkFeature from '../features/orcidlink';
import { LogIn } from '../features/login/LogIn';
import { LogInContinue } from '../features/login/LogInContinue';
import ORCIDLinkCreateLink from '../features/orcidlink/CreateLink';
import { LoggedOut } from '../features/login/LoggedOut';

export const LOGIN_ROUTE = '/login';
export const ROOT_REDIRECT_ROUTE = '/narratives';
Expand Down Expand Up @@ -57,6 +58,7 @@ const Routes: FC = () => {
{/* Log In */}
<Route path="/login" element={<LogIn />} />
<Route path="/login/continue" element={<LogInContinue />} />
<Route path="/loggedout" element={<LoggedOut />} />

{/* Navigator */}
<Route
Expand Down
33 changes: 3 additions & 30 deletions src/features/layout/TopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,15 @@ import { FontAwesomeIcon as FAIcon } from '@fortawesome/react-fontawesome';
import { FC, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';

import { toast } from 'react-hot-toast';
import { Link } from 'react-router-dom';
import { resetStateAction } from '../../app/store';
import { revokeToken } from '../../common/api/authService';
import { getUserProfile } from '../../common/api/userProfileApi';
import logo from '../../common/assets/logo/46_square.png';
import { Dropdown } from '../../common/components';
import { useAppDispatch, useAppSelector } from '../../common/hooks';
import { authUsername, setAuth } from '../auth/authSlice';
import { noOp } from '../common';
import { useAppSelector } from '../../common/hooks';
import { authUsername } from '../auth/authSlice';
import classes from './TopBar.module.scss';
import { LOGIN_ROUTE } from '../../app/Routes';
import { useLogout } from '../login/LogIn';

export default function TopBar() {
const username = useAppSelector(authUsername);
Expand Down Expand Up @@ -143,30 +140,6 @@ const UserMenu: FC = () => {
);
};

const useLogout = () => {
const tokenId = useAppSelector(({ auth }) => auth.tokenInfo?.id);
const dispatch = useAppDispatch();
const [revoke] = revokeToken.useMutation();
const navigate = useNavigate();

if (!tokenId) return noOp;

return () => {
revoke(tokenId)
.unwrap()
.then(() => {
dispatch(resetStateAction());
// setAuth(null) follow the state reset to initialize the page as un-Authed
dispatch(setAuth(null));
toast('You have been signed out');
navigate('/legacy/auth2/signedout');
})
.catch(() => {
toast('Error, could not log out.');
});
};
};

const HamburgerMenu: FC = () => {
const navigate = useNavigate();
return (
Expand Down
28 changes: 16 additions & 12 deletions src/features/legacy/Legacy.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { RefObject, useEffect, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { createSearchParams, useLocation, useNavigate } from 'react-router-dom';
import { usePageTitle } from '../layout/layoutSlice';
import { useTryAuthFromToken } from '../auth/hooks';
import { useAppDispatch } from '../../common/hooks';
import { resetStateAction } from '../../app/store';
import { setAuth } from '../auth/authSlice';
import { toast } from 'react-hot-toast';
import { LOGIN_ROUTE } from '../../app/Routes';
import { useLogout } from '../login/LogIn';

export const LEGACY_BASE_ROUTE = '/legacy';

Expand All @@ -17,7 +15,7 @@ export default function Legacy() {

const location = useLocation();
const navigate = useNavigate();
const dispatch = useAppDispatch();
const logout = useLogout();

const legacyContentRef = useRef<HTMLIFrameElement>(null);
const [legacyTitle, setLegacyTitle] = useState('');
Expand All @@ -43,8 +41,17 @@ export default function Legacy() {
let path = d.payload.request.original;
if (path[0] === '/') path = path.slice(1);
if (legacyPath !== path) {
setLegacyPath(path);
navigate(`./${path}`);
if (path === 'login') {
navigate({
pathname: LOGIN_ROUTE,
search: createSearchParams({
nextRequest: JSON.stringify(location),
}).toString(),
});
} else {
setLegacyPath(path);
navigate(`./${path}`);
}
}
} else if (isTitleMessage(d)) {
setLegacyTitle(d.payload);
Expand All @@ -53,10 +60,7 @@ export default function Legacy() {
setReceivedToken(d.payload.token);
}
} else if (isLogoutMessage(d)) {
dispatch(resetStateAction());
dispatch(setAuth(null));
toast('You have been signed out');
navigate('/legacy/auth2/signedout');
logout();
}
});

Expand Down
31 changes: 30 additions & 1 deletion src/features/login/LogIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ import orcidLogo from '../../common/assets/orcid.png';
import globusLogo from '../../common/assets/globus.png';
import googleLogo from '../../common/assets/google.webp';
import classes from './LogIn.module.scss';
import { useAppSelector } from '../../common/hooks';
import { useAppDispatch, useAppSelector } from '../../common/hooks';
import { useAppParam } from '../params/hooks';
import { To, useNavigate } from 'react-router-dom';
import { resetStateAction } from '../../app/store';
import { setAuth } from '../auth/authSlice';
import { toast } from 'react-hot-toast';
import { revokeToken } from '../../common/api/authService';
import { noOp } from '../common';

export const useCheckLoggedIn = (nextRequest: string | undefined) => {
const { initialized, token } = useAppSelector((state) => state.auth);
Expand All @@ -38,6 +43,30 @@ export const useCheckLoggedIn = (nextRequest: string | undefined) => {
}, [initialized, navigate, nextRequest, token]);
};

export const useLogout = () => {
const tokenId = useAppSelector(({ auth }) => auth.tokenInfo?.id);
const dispatch = useAppDispatch();
const [revoke] = revokeToken.useMutation();
const navigate = useNavigate();

if (!tokenId) return noOp;

return () => {
revoke(tokenId)
.unwrap()
.then(() => {
dispatch(resetStateAction());
// setAuth(null) follow the state reset to initialize the page as un-Authed
dispatch(setAuth(null));
toast('You have been signed out');
navigate('/loggedout');
})
.catch(() => {
toast('Error, could not log out.');
});
};
};

export const LogIn: FC = () => {
const nextRequest = useAppParam('nextRequest');
useCheckLoggedIn(nextRequest);
Expand Down
2 changes: 1 addition & 1 deletion src/features/login/LogInContinue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const LogInContinue: FC = () => {
if (choiceData) {
const accountExists = choiceData.login.length > 0;
// TODO: support choiceData.create cases
// TODO: support policy enforcement
if (accountExists) {
if (choiceData.login.length > 1) {
// needs to be implemented if we have multiple KBase accounts linked to one provider account
Expand Down Expand Up @@ -114,7 +115,6 @@ export const LogInContinue: FC = () => {
<Typography variant="h4" component="h1">
<Loader /> Logging in
</Typography>
<pre>{JSON.stringify(pickResult.data || choiceData, null, 4)}</pre>
</Stack>
</Paper>
</Stack>
Expand Down
93 changes: 93 additions & 0 deletions src/features/login/LoggedOut.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
Box,
Button,
Container,
Paper,
Stack,
Typography,
} from '@mui/material';
import { useCheckLoggedIn } from './LogIn';
import orcidLogo from '../../common/assets/orcid.png';
import globusLogo from '../../common/assets/globus.png';
import googleLogo from '../../common/assets/google.webp';
import classes from './LogIn.module.scss';

export const LoggedOut = () => {
useCheckLoggedIn(undefined);

return (
<Container maxWidth="sm">
<Stack spacing={2} textAlign="center">
<Paper
elevation={0}
sx={{
padding: 2,
}}
>
<Stack spacing={2}>
<Typography variant="h4" component="h1">
You are signed out of KBase
</Typography>
<Typography fontStyle="italic">
You may still be logged in to your identity provider. If you wish
to ensure that your KBase account is inaccessible from this
browser, you should sign out of any provider accounts you have
used to access KBase.
</Typography>
<Box className={classes['separator']} />
<Stack spacing={1}>
<Button
role="link"
href="https://www.orcid.org/signout"
variant="outlined"
color="base"
size="large"
startIcon={
<img
src={orcidLogo}
alt="ORCID logo"
className={classes['sso-logo']}
/>
}
>
Log out from ORCID
</Button>
<Button
role="link"
href="https://accounts.google.com/Logout"
variant="outlined"
color="base"
size="large"
startIcon={
<img
src={googleLogo}
alt="Google logo"
className={classes['sso-logo']}
/>
}
>
Log out from Google
</Button>
<Button
role="link"
href="https://app.globus.org/logout"
variant="outlined"
color="base"
size="large"
startIcon={
<img
src={globusLogo}
alt="Globus logo"
className={classes['sso-logo']}
/>
}
>
Log out from Globus
</Button>
</Stack>
</Stack>
</Paper>
</Stack>
</Container>
);
};

0 comments on commit 81b6d26

Please sign in to comment.