Skip to content

Commit

Permalink
feat: send login state as object with returnTo path
Browse files Browse the repository at this point in the history
  • Loading branch information
g-saracca committed Oct 15, 2024
1 parent bdc76d4 commit 882fbb9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
9 changes: 6 additions & 3 deletions src/router/ProtectedRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useContext, useEffect } from 'react'
import { Outlet, useLocation } from 'react-router-dom'
import { AuthContext } from 'react-oauth2-code-pkce'
import { AppLoader } from '../sections/shared/layout/app-loader/AppLoader'
import { encodeReturnToPathInStateQueryParam } from '@/sections/auth-callback/AuthCallback'

/**
* This component is responsible for protecting routes that require authentication.
Expand All @@ -10,16 +11,18 @@ import { AppLoader } from '../sections/shared/layout/app-loader/AppLoader'
*/

export const ProtectedRoute = () => {
const { pathname } = useLocation()
const { pathname, search } = useLocation()
const { token, loginInProgress, logIn: oidcLogin } = useContext(AuthContext)

useEffect(() => {
if (loginInProgress) return

if (!token) {
oidcLogin(encodeURIComponent(pathname))
const state = encodeReturnToPathInStateQueryParam(`${pathname}${search}`)

oidcLogin(state)
}
}, [token, oidcLogin, pathname, loginInProgress])
}, [token, oidcLogin, pathname, loginInProgress, search])

if (loginInProgress) {
return <AppLoader />
Expand Down
29 changes: 28 additions & 1 deletion src/sections/auth-callback/AuthCallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { AuthContext } from 'react-oauth2-code-pkce'
import { QueryParamKey } from '../Route.enum'
import { AppLoader } from '../shared/layout/app-loader/AppLoader'

export type AuthStateQueryParamValue = { returnTo: string }

/**
* This component will we rendered as redirectUri page after the OIDC login is complete.
* It will redirect the user to the intended page before the OIDC login was initiated.
Expand All @@ -25,8 +27,33 @@ export const AuthCallback = () => {
return
}

navigate(decodeURIComponent(stateQueryParam), { replace: true })
const returnToPath = decodeReturnToPathFromStateQueryParam(stateQueryParam)

navigate(returnToPath, { replace: true })
}, [stateQueryParam, navigate, loginInProgress])

return <AppLoader />
}

export const encodeReturnToPathInStateQueryParam = (returnToPath: string): string => {
const returnToObject: AuthStateQueryParamValue = { returnTo: returnToPath }

return encodeURIComponent(JSON.stringify(returnToObject))
}

export const decodeReturnToPathFromStateQueryParam = (stateQueryParam: string): string => {
const decodedStateQueryParam = decodeURIComponent(stateQueryParam)
const parsedStateQueryParam = JSON.parse(decodedStateQueryParam) as unknown

if (isReturnToObject(parsedStateQueryParam)) {
return parsedStateQueryParam.returnTo
}

return '/'
}

function isReturnToObject(obj: unknown): obj is AuthStateQueryParamValue {
return (
obj !== null && typeof obj === 'object' && 'returnTo' in obj && typeof obj.returnTo === 'string'
)
}
7 changes: 5 additions & 2 deletions src/sections/layout/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@ import { Route } from '@/sections/Route.enum'
import { useSession } from '@/sections/session/SessionContext'
import { LoggedInHeaderActions } from './LoggedInHeaderActions'
import { CollectionJSDataverseRepository } from '@/collection/infrastructure/repositories/CollectionJSDataverseRepository'
import { encodeReturnToPathInStateQueryParam } from '@/sections/auth-callback/AuthCallback'
import styles from './Header.module.scss'

const collectionRepository = new CollectionJSDataverseRepository()

export function Header() {
const { t } = useTranslation('header')
const { user } = useSession()
const { pathname } = useLocation()
const { pathname, search } = useLocation()

const { logIn: oidcLogin } = useContext(AuthContext)

const handleOidcLogIn = () => {
oidcLogin(encodeURIComponent(pathname))
const state = encodeReturnToPathInStateQueryParam(`${pathname}${search}`)

oidcLogin(state)
}

return (
Expand Down

0 comments on commit 882fbb9

Please sign in to comment.