@@ -6,6 +6,7 @@ import { getStsToken } from "@/lib/sts"
66import type { SiteConfig } from "@/types/config"
77import { getLoginRoute } from "@/lib/routes"
88import { useLocalStorage } from "@/hooks/use-local-storage"
9+ import { buildOidcLogoutUrl , type OidcLogoutSession } from "@/lib/oidc"
910
1011interface Credentials {
1112 AccessKeyId ?: string
@@ -19,9 +20,10 @@ interface AuthContextValue {
1920 credentials : AwsCredentialIdentity | AwsCredentialIdentityProvider ,
2021 customConfig ?: SiteConfig ,
2122 ) => Promise < unknown >
22- loginWithStsCredentials : ( credentials : Credentials ) => Promise < void >
23+ loginWithStsCredentials : ( credentials : Credentials , oidcSession ?: OidcLogoutSession ) => Promise < void >
2324 logout : ( ) => void
2425 logoutAndRedirect : ( ) => void
26+ logoutWithOidcRedirect : ( ) => Promise < boolean >
2527 setIsAdmin : ( value : boolean ) => void
2628 getIsAdmin : ( ) => boolean
2729 credentials : Credentials | undefined
@@ -44,9 +46,17 @@ function isValidCredentials(credentials: Credentials | undefined): boolean {
4446 return ! isExpired ( credentials . Expiration )
4547}
4648
49+ function isValidOidcLogoutSession ( session : OidcLogoutSession | undefined ) : session is OidcLogoutSession {
50+ return typeof session ?. logoutToken === "string" && session . logoutToken . trim ( ) . length > 0
51+ }
52+
4753export function AuthProvider ( { children } : { children : ReactNode } ) {
4854 const [ store , setStore ] = useLocalStorage < Credentials | undefined > ( "auth.credentials" , undefined )
4955 const [ isAdminStore , setIsAdminStore ] = useLocalStorage < boolean | undefined > ( "auth.isAdmin" , undefined )
56+ const [ oidcSessionStore , setOidcSessionStore ] = useLocalStorage < OidcLogoutSession | undefined > (
57+ "auth.oidcSession" ,
58+ undefined ,
59+ )
5060
5161 const setCredentials = useCallback (
5262 ( credentials : Credentials ) => {
@@ -67,6 +77,13 @@ export function AuthProvider({ children }: { children: ReactNode }) {
6777 [ setIsAdminStore ] ,
6878 )
6979
80+ const setOidcSession = useCallback (
81+ ( session : OidcLogoutSession | undefined ) => {
82+ setOidcSessionStore ( isValidOidcLogoutSession ( session ) ? session : undefined )
83+ } ,
84+ [ setOidcSessionStore ] ,
85+ )
86+
7087 const getIsAdmin = useCallback ( ( ) => {
7188 return ! ! isAdminStore
7289 } , [ isAdminStore ] )
@@ -87,34 +104,53 @@ export function AuthProvider({ children }: { children: ReactNode }) {
87104 SessionToken : credentialsResponse . SessionToken ,
88105 Expiration : credentialsResponse . Expiration ?. toISOString ( ) ,
89106 } )
107+ setOidcSession ( undefined )
90108
91109 return credentialsResponse
92110 } ,
93- [ setCredentials ] ,
111+ [ setCredentials , setOidcSession ] ,
94112 )
95113
96114 const loginWithStsCredentials = useCallback (
97- async ( creds : Credentials ) => {
115+ async ( creds : Credentials , oidcSession ?: OidcLogoutSession ) => {
98116 setCredentials ( {
99117 AccessKeyId : creds . AccessKeyId ,
100118 SecretAccessKey : creds . SecretAccessKey ,
101119 SessionToken : creds . SessionToken ,
102120 Expiration : creds . Expiration ,
103121 } )
122+ setOidcSession ( oidcSession )
104123 } ,
105- [ setCredentials ] ,
124+ [ setCredentials , setOidcSession ] ,
106125 )
107126
108127 const logout = useCallback ( ( ) => {
109128 setStore ( undefined )
110129 setIsAdminStore ( undefined )
111- } , [ setStore , setIsAdminStore ] )
130+ setOidcSessionStore ( undefined )
131+ } , [ setStore , setIsAdminStore , setOidcSessionStore ] )
112132
113133 const logoutAndRedirect = useCallback ( ( ) => {
114134 logout ( )
115135 window . location . href = getLoginRoute ( )
116136 } , [ logout ] )
117137
138+ const logoutWithOidcRedirect = useCallback ( async ( ) => {
139+ const oidcSession = isValidOidcLogoutSession ( oidcSessionStore ) ? oidcSessionStore : undefined
140+ logout ( )
141+
142+ if ( ! oidcSession ) return false
143+
144+ try {
145+ const { configManager } = await import ( "@/lib/config" )
146+ const config = await configManager . loadConfig ( )
147+ window . location . href = buildOidcLogoutUrl ( config . serverHost , oidcSession . logoutToken )
148+ return true
149+ } catch {
150+ return false
151+ }
152+ } , [ oidcSessionStore , logout ] )
153+
118154 const credentials = getCredentials ( )
119155 const isAuthenticated = isValidCredentials ( store )
120156
@@ -124,6 +160,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
124160 loginWithStsCredentials,
125161 logout,
126162 logoutAndRedirect,
163+ logoutWithOidcRedirect,
127164 setIsAdmin,
128165 getIsAdmin,
129166 credentials,
@@ -135,6 +172,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
135172 loginWithStsCredentials ,
136173 logout ,
137174 logoutAndRedirect ,
175+ logoutWithOidcRedirect ,
138176 setIsAdmin ,
139177 getIsAdmin ,
140178 credentials ,
0 commit comments