mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-21 19:29:51 -04:00
clean up authentication code
This commit is contained in:
parent
557d554db3
commit
dde3edee04
|
@ -14,10 +14,10 @@ const ION_AUTHORIZATION_ENDPOINT = dev
|
||||||
: 'https://ion.tjhsst.edu/oauth/authorize?response_type=code&client_id=rNa6n9YSg8ftINdyVPpUsaMuxNbHLo9dh1OsOktR&scope=read&redirect_uri=https%3A%2F%2Fwheelshare.space%2Fauth%2Fion%2Fcallback';
|
: 'https://ion.tjhsst.edu/oauth/authorize?response_type=code&client_id=rNa6n9YSg8ftINdyVPpUsaMuxNbHLo9dh1OsOktR&scope=read&redirect_uri=https%3A%2F%2Fwheelshare.space%2Fauth%2Fion%2Fcallback';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { isLoggedIn, user } = useContext(AuthenticationContext);
|
const { user } = useContext(AuthenticationContext);
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: '1rem' }}>
|
<div style={{ padding: '1rem' }}>
|
||||||
{isLoggedIn ? (
|
{user ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -28,7 +28,7 @@ export default function App() {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{user!.name}{' '}
|
{user.name}{' '}
|
||||||
<UIButton style={{ marginTop: 0 }} onClick={logout}>
|
<UIButton style={{ marginTop: 0 }} onClick={logout}>
|
||||||
Log out
|
Log out
|
||||||
</UIButton>
|
</UIButton>
|
||||||
|
|
|
@ -6,20 +6,19 @@ export type User = {
|
||||||
email?: string;
|
email?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AuthState = {
|
export type AuthenticationContextProps = {
|
||||||
isLoggedIn: boolean | null;
|
|
||||||
user: User | null;
|
user: User | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that can be used to trigger an auth state refresh.
|
* Function that can be used to trigger an auth state refresh.
|
||||||
*/
|
*/
|
||||||
refreshAuthState: (() => void) | null;
|
refresh: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AuthenticationContext = createContext<AuthState>({
|
const AuthenticationContext = createContext<AuthenticationContextProps>({
|
||||||
isLoggedIn: false,
|
|
||||||
user: null,
|
user: null,
|
||||||
refreshAuthState: null,
|
refresh: () =>
|
||||||
|
console.warn('calling refresh on default AuthenticationContext'),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default AuthenticationContext;
|
export default AuthenticationContext;
|
||||||
|
|
|
@ -1,45 +1,30 @@
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { getMe } from '../api';
|
import { getMe } from '../api';
|
||||||
import AuthenticationContext, { AuthState } from './AuthenticationContext';
|
import AuthenticationContext, { User } from './AuthenticationContext';
|
||||||
|
|
||||||
export default function AuthenticationWrapper({
|
export default function AuthenticationWrapper({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const sessionToken = localStorage.getItem('session_token');
|
|
||||||
// Prevent race conditions
|
// Prevent race conditions
|
||||||
const [authState, setAuthState] = useState<AuthState>({
|
const [user, setUser] = useState<User | null>(null);
|
||||||
isLoggedIn: null,
|
|
||||||
user: null,
|
|
||||||
refreshAuthState: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
const refreshAuthState = useCallback(() => {
|
const refresh = useCallback(() => {
|
||||||
const loggedOut = () =>
|
const none = () => setUser(null);
|
||||||
setAuthState({ isLoggedIn: false, user: null, refreshAuthState });
|
const sessionToken = localStorage.getItem('session_token');
|
||||||
|
|
||||||
if (sessionToken) {
|
if (sessionToken) {
|
||||||
getMe()
|
getMe().then(setUser).catch(none);
|
||||||
.then((user) => {
|
|
||||||
if (user) {
|
|
||||||
setAuthState({ isLoggedIn: true, user, refreshAuthState });
|
|
||||||
} else {
|
} else {
|
||||||
loggedOut();
|
none();
|
||||||
}
|
}
|
||||||
})
|
}, []);
|
||||||
.catch(loggedOut);
|
|
||||||
} else {
|
|
||||||
loggedOut();
|
|
||||||
}
|
|
||||||
}, [sessionToken]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(refresh, [refresh]);
|
||||||
refreshAuthState();
|
|
||||||
}, [refreshAuthState]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthenticationContext.Provider value={authState}>
|
<AuthenticationContext.Provider value={{ user, refresh }}>
|
||||||
{children}
|
{children}
|
||||||
</AuthenticationContext.Provider>
|
</AuthenticationContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,45 +3,51 @@ import { Redirect, useLocation, useParams } from 'react-router-dom';
|
||||||
import AuthenticationContext from './AuthenticationContext';
|
import AuthenticationContext from './AuthenticationContext';
|
||||||
import { createSession } from './createSession';
|
import { createSession } from './createSession';
|
||||||
|
|
||||||
|
function useCode() {
|
||||||
|
const location = useLocation();
|
||||||
|
const query = new URLSearchParams(location.search);
|
||||||
|
const code = query.get('code');
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
export default function Authenticator() {
|
export default function Authenticator() {
|
||||||
const { provider } = useParams<{ provider: string }>();
|
const { provider } = useParams<{ provider: string }>();
|
||||||
const query = new URLSearchParams(useLocation().search);
|
const code = useCode();
|
||||||
const code = query.get('code');
|
const { refresh } = useContext(AuthenticationContext);
|
||||||
const { refreshAuthState } = useContext(AuthenticationContext);
|
|
||||||
const [status, setStatus] =
|
const [pending, setPending] = useState(true);
|
||||||
useState<'pending' | 'errored' | 'authenticated'>('pending');
|
|
||||||
const [token, setToken] = useState<string | null>(null);
|
const [token, setToken] = useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
createSession(code!)
|
if (token) {
|
||||||
.then((data) => {
|
localStorage.setItem('session_token', token);
|
||||||
if (data.status === 'success') {
|
|
||||||
console.log('Success! Token:', data.token);
|
|
||||||
setToken(data.token);
|
|
||||||
localStorage.setItem('session_token', data.token);
|
|
||||||
setStatus('authenticated');
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Authentication failure.');
|
|
||||||
setToken(null);
|
|
||||||
localStorage.removeItem('session_token');
|
localStorage.removeItem('session_token');
|
||||||
setStatus('errored');
|
|
||||||
}
|
}
|
||||||
|
}, [token]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setPending(true);
|
||||||
|
createSession(code!)
|
||||||
|
.then(({ token }) => {
|
||||||
|
setToken(token ?? null);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.finally(() => setPending(false));
|
||||||
setStatus('errored');
|
|
||||||
});
|
|
||||||
}, [code, provider]);
|
}, [code, provider]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
refreshAuthState && refreshAuthState();
|
refresh();
|
||||||
}, [token, refreshAuthState]);
|
}, [token, refresh]);
|
||||||
|
|
||||||
switch (status) {
|
if (pending) {
|
||||||
case 'authenticated':
|
|
||||||
return <Redirect to="/" />;
|
|
||||||
case 'errored':
|
|
||||||
return <h1>Sign In Error</h1>;
|
|
||||||
case 'pending':
|
|
||||||
return <h1>Signing In</h1>;
|
return <h1>Signing In</h1>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
return <Redirect to="/" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we aren't pending anymore, but don't have a token, we must have errored
|
||||||
|
return <h1>Sign In Error</h1>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user