@@ -7,9 +7,11 @@ import React, { createContext, useContext, useState, useMemo, useRef, useEffect
77import { oidcSession , mockedSession , tokenSession } from "@cloudoperators/juno-oauth"
88import { createAuthStore , AuthStore } from "@cloudoperators/greenhouse-auth-provider"
99import { extractOrganizationName } from "../utils/organizationResolver"
10+ import { TokenDataSchema } from "../types/auth"
11+ import type { OidcSessionState , AuthContextValue , OidcSessionInstance , TokenData , MockAuthValue } from "../types/auth"
1012
11- const setOrganizationToUrl = ( groups : any , enableHashedRouting : boolean ) => {
12- const orgName = groups ?. find ( ( g : any ) => g . startsWith ( "organization:" ) ) ?. split ( ":" ) [ 1 ]
13+ const setOrganizationToUrl = ( groups : string [ ] | undefined , enableHashedRouting : boolean ) => {
14+ const orgName = groups ?. find ( ( g : string ) => g . startsWith ( "organization:" ) ) ?. split ( ":" ) [ 1 ]
1315
1416 if ( ! orgName ) return
1517
@@ -34,43 +36,58 @@ const setOrganizationToUrl = (groups: any, enableHashedRouting: boolean) => {
3436 } else {
3537 url . pathname = pathWithOrg
3638 }
37- // @ts -expect-error TS(2345): Argument of type 'null' is not assignable to param... Remove this comment to see the full error message
38- window . history . replaceState ( null , null , url . href )
39+ window . history . replaceState ( { } , "" , url . href )
3940}
4041
41- function resolveMockAuth ( value : any ) {
42- const result = { isMock : false , parsedAuth : null }
43-
42+ /**
43+ * Resolves mock authentication configuration with runtime validation
44+ *
45+ * @param value - Can be:
46+ * - boolean: true enables mock with default token, false disables
47+ * - TokenData: Plain object with token attributes (iss, sub, aud, exp, iat, nonce, email, groups, etc.)
48+ * - string: "true" or JSON string that will be parsed
49+ *
50+ * @returns Object with isMock flag and parsedAuth token data
51+ */
52+ function resolveMockAuth ( value : MockAuthValue ) : { isMock : boolean ; parsedAuth : TokenData | null } {
4453 if ( typeof value === "boolean" ) {
45- // If value is a boolean, set `isMock` accordingly
46- // and return an empty object for `true`, otherwise `null`
47- result . isMock = value
48- // @ts -expect-error TS(2322): Type '{} | null' is not assignable to type 'null'.
49- result . parsedAuth = value ? { } : null
50- } else if ( typeof value === "string" ) {
51- const trimmed = value . trim ( ) . toLowerCase ( )
52- if ( trimmed === "true" ) {
53- // If the string is "true", treat it as a mock with an empty object
54- result . isMock = true
55- // @ts -expect-error TS(2322): Type '{}' is not assignable to type 'null'.
56- result . parsedAuth = { }
57- } else {
58- try {
59- // Try parsing the string as JSON
60- result . isMock = true
61- result . parsedAuth = JSON . parse ( value )
62- } catch {
63- result . isMock = false
64- result . parsedAuth = null
54+ return {
55+ isMock : value ,
56+ parsedAuth : value ? { } : null ,
57+ }
58+ }
59+
60+ if ( typeof value === "string" ) {
61+ const trimmed = value . trim ( )
62+ // Only lowercase for boolean check, not for JSON parsing
63+ if ( trimmed . toLowerCase ( ) === " true" ) {
64+ return { isMock : true , parsedAuth : { } }
65+ }
66+
67+ // Try parsing JSON string (use original case-sensitive trimmed string)
68+ try {
69+ const parsed = JSON . parse ( trimmed )
70+ // Validate the parsed JSON
71+ const validation = TokenDataSchema . safeParse ( parsed )
72+ if ( validation . success ) {
73+ return { isMock : true , parsedAuth : validation . data }
6574 }
75+ } catch {
76+ // Invalid JSON, return disabled mock
6677 }
67- } else if ( typeof value === "object" && value !== null ) {
68- // If value is a non-null object, treat it as a mock
69- result . isMock = true
70- result . parsedAuth = value
78+
79+ return { isMock : false , parsedAuth : null }
80+ }
81+
82+ // It's an object - validate with Zod to ensure runtime safety
83+ const validation = TokenDataSchema . safeParse ( value )
84+ if ( validation . success ) {
85+ return { isMock : true , parsedAuth : validation . data }
7186 }
7287
73- return result
88+ // Invalid object (e.g., array, number, invalid structure)
89+ console . warn ( "Invalid mockAuth value: expected boolean, TokenData object, or JSON string" , value )
90+ return { isMock : false , parsedAuth : null }
7491}
7592
7693const initializeDemoAuth = (
@@ -163,14 +180,13 @@ const initializeRealOidc = (
163180 } )
164181}
165182
166- // @ts -expect-error TS(2554): Expected 1 arguments, but got 0.
167- const AuthContext = createContext ( )
183+ const AuthContext = createContext < AuthContextValue | undefined > ( undefined )
168184
169185export const AuthProvider = ( { options, children } : any ) => {
170- const [ authData , setAuthData ] = useState ( null )
186+ const [ authData , setAuthData ] = useState < OidcSessionState | null > ( null )
171187 const [ isDemoMode , setIsDemoMode ] = useState ( false )
172- const [ oidcError , setOidcError ] = useState ( null )
173- const oidcInstance = useRef ( null )
188+ const [ oidcError , setOidcError ] = useState < string | null > ( null )
189+ const oidcInstance = useRef < OidcSessionInstance | null > ( null )
174190 const pluginAuthRef = useRef < AuthStore | null > ( null )
175191
176192 if ( ! pluginAuthRef . current ) {
@@ -201,7 +217,6 @@ export const AuthProvider = ({ options, children }: any) => {
201217 if ( demoOrg === orgName && ! isMock ) {
202218 console . debug ( "Initializing new demo auth session" )
203219 setIsDemoMode ( true )
204- // @ts -ignore
205220 oidcInstance . current = initializeDemoAuth (
206221 orgName ,
207222 demoUserToken ,
@@ -245,42 +260,34 @@ export const AuthProvider = ({ options, children }: any) => {
245260
246261 const error = "Invalid OIDC configuration, issuerURL and clientID are required"
247262 console . error ( error )
248- // @ts -expect-error TS(2345): Argument of type '"Invalid OIDC configuration, iss... Remove this comment to see the full error message
249263 setOidcError ( error )
250- return
264+ return null
251265 }
252266
253267 // Memoized login function
254268 const login = ( ) => {
255- // @ts -expect-error TS(2339): Property 'login' does not exist on type 'never'.
256- oidcInstance . current ?. login ?.( )
269+ oidcInstance . current ?. login ( )
257270 }
258271
259272 // Memoized logout function
260- const logout = ( ) => {
261- // @ts -expect-error TS(2339): Property 'logout' does not exist on type 'never'.
262- oidcInstance . current ?. logout ?.( {
263- resetOIDCSession : true ,
264- silent : true ,
273+ const logout = ( options ?: { resetOIDCSession ?: boolean ; silent ?: boolean } ) => {
274+ oidcInstance . current ?. logout ( {
275+ resetOIDCSession : options ?. resetOIDCSession ?? true ,
276+ silent : options ?. silent ?? true ,
265277 } )
266278 setAuthData ( null )
267279 setOidcError ( null )
268280 }
269281
270282 useEffect ( ( ) => {
271- // @ts -expect-error TS(2322): Type 'null | undefined' is not assignable to type ... Remove this comment to see the full error message
272283 oidcInstance . current = initializeOidc ( )
273284 } , [ options ] )
274285
275286 const contextValue = useMemo (
276287 ( ) => ( {
277- // @ts -expect-error TS(2339): Property 'isProcessing' does not exist on type 'ne... Remove this comment to see the full error message
278288 isProcessing : authData ? authData ?. isProcessing : false ,
279- // @ts -expect-error TS(2339): Property 'loggedIn' does not exist on type 'never'... Remove this comment to see the full error message
280289 loggedIn : authData ? authData ?. loggedIn : false ,
281- // @ts -expect-error TS(2339): Property 'error' does not exist on type 'never'.
282290 error : authData ? authData ?. error : oidcError ,
283- // @ts -expect-error TS(2339): Property 'auth' does not exist on type 'never'.
284291 data : authData ? authData ?. auth : null ,
285292 pluginAuth,
286293 isDemoMode,
@@ -293,6 +300,10 @@ export const AuthProvider = ({ options, children }: any) => {
293300 return < AuthContext . Provider value = { contextValue } > { children } </ AuthContext . Provider >
294301}
295302
296- export const useAuth = ( ) => {
297- return useContext ( AuthContext )
303+ export const useAuth = ( ) : AuthContextValue => {
304+ const context = useContext ( AuthContext )
305+ if ( context === undefined ) {
306+ throw new Error ( "useAuth must be used within an AuthProvider" )
307+ }
308+ return context
298309}
0 commit comments