diff --git a/src/app/routes/Landing.tsx b/src/app/routes/Landing.tsx index 4333587..1011323 100644 --- a/src/app/routes/Landing.tsx +++ b/src/app/routes/Landing.tsx @@ -2,7 +2,7 @@ import { useNavigate } from 'react-router' import { useEffect} from "react" import BungieLogin from '../../features/auth/BungieLogin' -import { generateToken, regenerateTokens } from '../../lib/bungie_api/TokenService' +import { regenerateTokens } from '../../lib/bungie_api/TokenService' import { isAuthenticated } from '../../lib/bungie_api/AuthService' @@ -20,6 +20,8 @@ export const LandingRoute = () => { navigate('/app') } + console.log("Not authenticated") + }, []) return ( diff --git a/src/app/routes/Return.tsx b/src/app/routes/Return.tsx index 595763d..ae1e4d7 100644 --- a/src/app/routes/Return.tsx +++ b/src/app/routes/Return.tsx @@ -2,6 +2,9 @@ import { useEffect } from "react" import { useNavigate } from "react-router-dom" import { handleAuthReturn } from "../../features/auth/AuthReturn" +/** + * Bungie OAuth redirects here + */ export const ReturnRoute = () => { const navigate = useNavigate() @@ -9,6 +12,7 @@ export const ReturnRoute = () => { useEffect( () => { if (handleAuthReturn()) { + // exit component if successful navigate('/') } diff --git a/src/features/auth/AuthReturn.tsx b/src/features/auth/AuthReturn.tsx index cbd6461..d742002 100644 --- a/src/features/auth/AuthReturn.tsx +++ b/src/features/auth/AuthReturn.tsx @@ -5,6 +5,10 @@ function getAuthCodeFromURL(): string | null { return window.location.href.includes("code=") ? window.location.href.split('code=')[1] : null } +/** + * Get auth tokens from auth code + * @returns whether or not tokens were successfully generated + */ export function handleAuthReturn(): boolean { const code = getAuthCodeFromURL() diff --git a/src/lib/bungie_api/AuthService.tsx b/src/lib/bungie_api/AuthService.tsx index e94a914..53e5c73 100644 --- a/src/lib/bungie_api/AuthService.tsx +++ b/src/lib/bungie_api/AuthService.tsx @@ -2,10 +2,18 @@ import { Navigate } from "react-router-dom" import { isTokenExpired } from "./TokenService" import { getTokens } from "./TokensStore" +/** + * Navigates to the Bungie OAuth url + */ export function authenticate(): void { window.location.replace(`https://www.bungie.net/en/OAuth/Authorize?client_id=${import.meta.env.VITE_CLIENT_ID}&response_type=code`) } +/** + * Whether or not the user is authenticated. + * + * @returns if auth tokens are present in local store + */ export function isAuthenticated(): boolean { const tokens = getTokens() @@ -13,6 +21,9 @@ export function isAuthenticated(): boolean { return !tokens ? false : !isTokenExpired(tokens.accessToken) } +/** + * Restricts rendering of children if not authenticated + */ export const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { if (!isAuthenticated()) { diff --git a/src/lib/bungie_api/BungieApiClient.ts b/src/lib/bungie_api/BungieApiClient.ts index 1627e1b..ba08582 100644 --- a/src/lib/bungie_api/BungieApiClient.ts +++ b/src/lib/bungie_api/BungieApiClient.ts @@ -9,10 +9,23 @@ const apiClient = axios.create({ } }) +/** + * Bungie get request + * @param url + * @param config axios config + * @returns + */ const _get = (url: string, config = {}) => { return apiClient.get(url, config) } +/** + * Bungie post request + * @param url + * @param data request body + * @param config axios config + * @returns + */ const _post = (url: string, data = {}, config = {}) => { return apiClient.post(url, data, config) } diff --git a/src/lib/bungie_api/TokenService.ts b/src/lib/bungie_api/TokenService.ts index be22f52..c0a3bb9 100644 --- a/src/lib/bungie_api/TokenService.ts +++ b/src/lib/bungie_api/TokenService.ts @@ -34,8 +34,14 @@ export function isTokenExpired(token?: Token) { return Date.now() > expiration } -function getTokenExpiration(token?: Token): number { - return (token && 'acquired' in token && 'expires' in token) ? token.acquired + token.expires * 1000 : 0 +export function regenerateTokens(): boolean { + + if (canTokensRefresh()) { + generateToken(true) + return true + } + + return false } export function generateToken(refresh: boolean, authCode=""): Tokens | null { @@ -68,6 +74,10 @@ export function generateToken(refresh: boolean, authCode=""): Tokens | null { return returnToken } +function getTokenExpiration(token?: Token): number { + return (token && 'acquired' in token && 'expires' in token) ? token.acquired + token.expires * 1000 : 0 +} + function handleTokenResponse(response: AxiosResponse): Tokens { if (response.data.access_token) { @@ -98,14 +108,4 @@ function handleTokenResponse(response: AxiosResponse): Tokens { else { throw new Error(`Invalid response: ${JSON.stringify(response)}`) } -} - -export function regenerateTokens(): boolean { - - if (canTokensRefresh()) { - generateToken(true) - return true - } - - return false } \ No newline at end of file diff --git a/src/lib/bungie_api/TokensStore.ts b/src/lib/bungie_api/TokensStore.ts index 87d37aa..869734f 100644 --- a/src/lib/bungie_api/TokensStore.ts +++ b/src/lib/bungie_api/TokensStore.ts @@ -14,19 +14,33 @@ export interface Tokens { const key = 'authTokens' +/** + * Gets the locally stored auth tokens + * @returns the tokens or null + */ export function getTokens(): Tokens | null { const tokenString = localStorage.getItem(key) return tokenString ? (JSON.parse(tokenString) as Tokens) : null } +/** + * Stores auth tokens in local storage. + */ export function setTokens(tokens: Tokens) { localStorage.setItem(key, JSON.stringify(tokens)) } +/** + * Removes the locally stored auth tokens + */ export function removeTokens() { localStorage.removeItem(key) } +/** + * Gets the membersip id from the locally stored auth tokens + * @returns membershipId + */ export function getMembershipId(): string | undefined { const tokens = getTokens()