@civic/auth 0.7.0-beta.1 โ 0.7.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +19 -1
- package/dist/nextjs/config.d.ts +1 -0
- package/dist/nextjs/config.d.ts.map +1 -1
- package/dist/nextjs/config.js +2 -4
- package/dist/nextjs/config.js.map +1 -1
- package/dist/nextjs/hooks/useRefresh.d.ts.map +1 -1
- package/dist/nextjs/hooks/useRefresh.js +7 -1
- package/dist/nextjs/hooks/useRefresh.js.map +1 -1
- package/dist/nextjs/hooks/useUserCookie.d.ts.map +1 -1
- package/dist/nextjs/hooks/useUserCookie.js.map +1 -1
- package/dist/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
- package/dist/nextjs/providers/NextAuthProvider.js +4 -3
- package/dist/nextjs/providers/NextAuthProvider.js.map +1 -1
- package/dist/nextjs/routeHandler.d.ts.map +1 -1
- package/dist/nextjs/routeHandler.js +7 -0
- package/dist/nextjs/routeHandler.js.map +1 -1
- package/dist/reactjs/components/SignInButton.d.ts.map +1 -1
- package/dist/reactjs/components/SignInButton.js +8 -3
- package/dist/reactjs/components/SignInButton.js.map +1 -1
- package/dist/reactjs/components/SignOutButton.d.ts.map +1 -1
- package/dist/reactjs/components/SignOutButton.js +3 -1
- package/dist/reactjs/components/SignOutButton.js.map +1 -1
- package/dist/reactjs/components/UserButton.d.ts.map +1 -1
- package/dist/reactjs/components/UserButton.js +11 -6
- package/dist/reactjs/components/UserButton.js.map +1 -1
- package/dist/reactjs/components/index.d.ts +5 -5
- package/dist/reactjs/components/index.d.ts.map +1 -1
- package/dist/reactjs/components/index.js +5 -5
- package/dist/reactjs/components/index.js.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.d.ts +120 -0
- package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -0
- package/dist/reactjs/core/GlobalAuthManager.js +296 -0
- package/dist/reactjs/core/GlobalAuthManager.js.map +1 -0
- package/dist/reactjs/hooks/index.d.ts +2 -2
- package/dist/reactjs/hooks/index.d.ts.map +1 -1
- package/dist/reactjs/hooks/index.js +2 -2
- package/dist/reactjs/hooks/index.js.map +1 -1
- package/dist/reactjs/hooks/useToken.d.ts +13 -0
- package/dist/reactjs/hooks/useToken.d.ts.map +1 -0
- package/dist/reactjs/hooks/useToken.js +48 -0
- package/dist/reactjs/hooks/useToken.js.map +1 -0
- package/dist/reactjs/hooks/useUser.d.ts +20 -2
- package/dist/reactjs/hooks/useUser.d.ts.map +1 -1
- package/dist/reactjs/hooks/useUser.js +163 -7
- package/dist/reactjs/hooks/useUser.js.map +1 -1
- package/dist/reactjs/index.d.ts +6 -2
- package/dist/reactjs/index.d.ts.map +1 -1
- package/dist/reactjs/index.js +7 -1
- package/dist/reactjs/index.js.map +1 -1
- package/dist/reactjs/providers/CivicAuthContext.d.ts +40 -0
- package/dist/reactjs/providers/CivicAuthContext.d.ts.map +1 -0
- package/dist/reactjs/providers/CivicAuthContext.js +303 -0
- package/dist/reactjs/providers/CivicAuthContext.js.map +1 -0
- package/dist/reactjs/providers/CivicAuthProvider.d.ts +20 -4
- package/dist/reactjs/providers/CivicAuthProvider.d.ts.map +1 -1
- package/dist/reactjs/providers/CivicAuthProvider.js +46 -24
- package/dist/reactjs/providers/CivicAuthProvider.js.map +1 -1
- package/dist/reactjs/providers/index.d.ts +2 -2
- package/dist/reactjs/providers/index.d.ts.map +1 -1
- package/dist/reactjs/providers/index.js +4 -2
- package/dist/reactjs/providers/index.js.map +1 -1
- package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
- package/dist/server/ServerAuthenticationResolver.js +28 -11
- package/dist/server/ServerAuthenticationResolver.js.map +1 -1
- package/dist/server/config.d.ts +2 -0
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js.map +1 -1
- package/dist/server/login.d.ts +2 -2
- package/dist/server/login.d.ts.map +1 -1
- package/dist/server/login.js +7 -2
- package/dist/server/login.js.map +1 -1
- package/dist/services/AuthenticationService.d.ts +1 -1
- package/dist/services/AuthenticationService.d.ts.map +1 -1
- package/dist/services/AuthenticationService.js +2 -2
- package/dist/services/AuthenticationService.js.map +1 -1
- package/dist/shared/components/CivicAuthIframe.js +1 -1
- package/dist/shared/components/CivicAuthIframe.js.map +1 -1
- package/dist/shared/components/CivicAuthIframeContainer.js +2 -2
- package/dist/shared/components/CivicAuthIframeContainer.js.map +1 -1
- package/dist/shared/hooks/index.d.ts +1 -2
- package/dist/shared/hooks/index.d.ts.map +1 -1
- package/dist/shared/hooks/index.js +1 -2
- package/dist/shared/hooks/index.js.map +1 -1
- package/dist/shared/hooks/useClientTokenExchangeSession.d.ts +7 -0
- package/dist/shared/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
- package/dist/shared/hooks/useClientTokenExchangeSession.js +17 -0
- package/dist/shared/hooks/useClientTokenExchangeSession.js.map +1 -0
- package/dist/shared/hooks/useSignIn.d.ts +4 -9
- package/dist/shared/hooks/useSignIn.d.ts.map +1 -1
- package/dist/shared/hooks/useSignIn.js +42 -75
- package/dist/shared/hooks/useSignIn.js.map +1 -1
- package/dist/shared/lib/BrowserAuthenticationRefresher.js +3 -3
- package/dist/shared/lib/BrowserAuthenticationRefresher.js.map +1 -1
- package/dist/shared/lib/types.d.ts +1 -1
- package/dist/shared/lib/types.js +1 -1
- package/dist/shared/lib/types.js.map +1 -1
- package/dist/shared/lib/util.d.ts +5 -6
- package/dist/shared/lib/util.d.ts.map +1 -1
- package/dist/shared/lib/util.js +66 -75
- package/dist/shared/lib/util.js.map +1 -1
- package/dist/shared/providers/AuthContext.d.ts +2 -7
- package/dist/shared/providers/AuthContext.d.ts.map +1 -1
- package/dist/shared/providers/AuthContext.js.map +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.d.ts +2 -2
- package/dist/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.js +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.js.map +1 -1
- package/dist/shared/providers/TokenProvider.d.ts.map +1 -1
- package/dist/shared/providers/TokenProvider.js +4 -7
- package/dist/shared/providers/TokenProvider.js.map +1 -1
- package/dist/shared/providers/UserProvider.d.ts +1 -5
- package/dist/shared/providers/UserProvider.d.ts.map +1 -1
- package/dist/shared/providers/UserProvider.js.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +23 -0
- package/dist/utils.js.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.d.ts +12 -0
- package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.js +88 -5
- package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
- package/dist/vanillajs/auth/SessionManager.d.ts +7 -1
- package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
- package/dist/vanillajs/auth/SessionManager.js +34 -3
- package/dist/vanillajs/auth/SessionManager.js.map +1 -1
- package/dist/vanillajs/auth/TokenRefresher.js +2 -2
- package/dist/vanillajs/auth/TokenRefresher.js.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.js +7 -2
- package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.d.ts +3 -0
- package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
- package/dist/vanillajs/index.d.ts +2 -0
- package/dist/vanillajs/index.d.ts.map +1 -1
- package/dist/vanillajs/index.js +2 -0
- package/dist/vanillajs/index.js.map +1 -1
- package/dist/vanillajs/types/index.d.ts +1 -1
- package/dist/vanillajs/types/index.d.ts.map +1 -1
- package/dist/vanillajs/types/index.js.map +1 -1
- package/dist/vanillajs/utils/auth-utils.d.ts +14 -0
- package/dist/vanillajs/utils/auth-utils.d.ts.map +1 -1
- package/dist/vanillajs/utils/auth-utils.js +39 -0
- package/dist/vanillajs/utils/auth-utils.js.map +1 -1
- package/package.json +1 -1
- package/dist/reactjs/hooks/useClientTokenExchangeSession.d.ts +0 -3
- package/dist/reactjs/hooks/useClientTokenExchangeSession.d.ts.map +0 -1
- package/dist/reactjs/hooks/useClientTokenExchangeSession.js +0 -13
- package/dist/reactjs/hooks/useClientTokenExchangeSession.js.map +0 -1
- package/dist/reactjs/providers/AuthProvider.d.ts +0 -10
- package/dist/reactjs/providers/AuthProvider.d.ts.map +0 -1
- package/dist/reactjs/providers/AuthProvider.js +0 -79
- package/dist/reactjs/providers/AuthProvider.js.map +0 -1
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts +0 -17
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts.map +0 -1
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.js +0 -190
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserProvider.js","sourceRoot":"","sources":["../../../src/shared/providers/UserProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAS/E,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"UserProvider.js","sourceRoot":"","sources":["../../../src/shared/providers/UserProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport React, { createContext, useCallback, useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type {\n AuthStatus,\n AuthStorage,\n DisplayMode,\n ForwardedTokens,\n User,\n} from \"@/types.js\";\nimport { useSession } from \"@/shared/hooks/useSession.js\";\nimport type { AuthContextType } from \"@/shared/providers/AuthContext.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport { useToken } from \"../hooks/useToken.js\";\nimport type { JWTPayload } from \"jose\";\n\ntype UserContent = Record<string, unknown> & JWTPayload;\ntype UserContextType<T extends UserContent = UserContent> = {\n user: User<T> | null;\n} & {\n accessToken?: string | null;\n idToken?: string | null;\n forwardedTokens?: ForwardedTokens;\n} & Omit<AuthContextType, \"isAuthenticated\">;\n\nconst UserContext = createContext<UserContextType | null>(null);\n\nconst UserProvider = <T extends UserContent>({\n children,\n storage,\n user: inputUser,\n signOut,\n authStatus,\n signIn,\n displayMode,\n}: {\n children: ReactNode;\n storage: AuthStorage;\n user: User<T> | null;\n signOut: () => Promise<void>;\n authStatus: AuthStatus;\n signIn: (displayMode?: DisplayMode) => Promise<void>;\n displayMode: DisplayMode;\n}) => {\n const {\n data: session,\n error: authError,\n isLoading: authLoading,\n } = useSession();\n const tokens = useToken();\n const [userLoading, setUserLoading] = useState<boolean>(false);\n const [userError, setUserError] = useState<Error | null>(null);\n const [user, setUser] = useState<User<T> | null>(inputUser);\n\n const fetchUser = useCallback(async (): Promise<User<T> | null> => {\n if (!session?.idToken) return null;\n const userSession = new GenericUserSession<T>(storage);\n return userSession.get();\n }, [session?.idToken, storage]);\n\n useEffect(() => {\n if (session?.idToken) {\n setUserLoading(true);\n fetchUser()\n .then((user) => {\n setUserLoading(false);\n setUser((prevUser) => {\n // we only want to update the user if it's set - if a user is passed in, don't assume it is wrong here\n // it could be just the fetchUser returned null for some other reason.\n // TODO consider cleaning this up in general to avoid needing context here.\n return user ?? prevUser;\n });\n })\n .catch((error) => {\n setUserLoading(false);\n setUserError(error);\n });\n } else {\n setUser(null);\n }\n }, [fetchUser, session?.idToken]);\n\n const isLoading = authLoading || userLoading;\n const error = authError ?? userError;\n\n // While we are passing a user as a prop _and_ storing it in state,\n // there is the case where the user is not set in the state yet\n // (setState is called but the rerender has not yet happened), but\n // is passed as a prop. In this case, we want to use the prop value.\n // A better solution is to avoid having multiple layers of context.\n // If the user is passed in, we just use that.\n // We should not split user state management across multiple contexts\n const userValue = user ?? inputUser;\n\n return (\n <UserContext.Provider\n value={{\n ...tokens,\n user: userValue,\n isLoading,\n error,\n signIn,\n signOut,\n authStatus,\n displayMode: displayMode || \"iframe\",\n }}\n >\n {children}\n </UserContext.Provider>\n );\n};\n\nexport type { UserContextType };\n\nexport { UserProvider, UserContext };\n"]}
|
package/dist/shared/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "@civic/auth:0.7.
|
|
1
|
+
export declare const VERSION = "@civic/auth:0.7.1-beta.1";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/shared/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/shared/version.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.7.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/shared/version.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.7.1-beta.1\";\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ type SessionData = {
|
|
|
55
55
|
accessToken?: string;
|
|
56
56
|
refreshToken?: string;
|
|
57
57
|
idToken?: string;
|
|
58
|
-
|
|
58
|
+
oidcSessionExpiresAt?: number;
|
|
59
59
|
codeVerifier?: string;
|
|
60
60
|
displayMode?: DisplayMode;
|
|
61
61
|
openerUrl?: string;
|
|
@@ -63,7 +63,7 @@ type SessionData = {
|
|
|
63
63
|
type OIDCTokenResponseBody = {
|
|
64
64
|
id_token: string;
|
|
65
65
|
access_token?: string;
|
|
66
|
-
|
|
66
|
+
oidc_session_expires_at?: number;
|
|
67
67
|
refresh_token?: string;
|
|
68
68
|
expires_in?: number;
|
|
69
69
|
token_type?: string;
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,MAAM,CAAN,IAAY,UAMX;AAND,WAAY,UAAU;IACpB,6CAA+B,CAAA;IAC/B,iDAAmC,CAAA;IACnC,+CAAiC,CAAA;IACjC,6BAAe,CAAA;IACf,yCAA2B,CAAA;AAC7B,CAAC,EANW,UAAU,KAAV,UAAU,QAMrB;AAsID,MAAM,SAAS,GAAG;IAChB,KAAK;IACL,SAAS;IACT,aAAa;IACb,cAAc;IACd,iBAAiB;CACT,CAAC;AAsGX,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import type { JWTPayload } from \"jose\";\n\ntype UnknownObject = Record<string, unknown>;\ntype EmptyObject = Record<string, never>;\n\nexport enum AuthStatus {\n AUTHENTICATED = \"authenticated\",\n UNAUTHENTICATED = \"unauthenticated\",\n AUTHENTICATING = \"authenticating\",\n ERROR = \"error\",\n SIGNING_OUT = \"signing_out\",\n}\n// Display modes for the auth flow\ntype DisplayMode = \"iframe\" | \"redirect\" | \"new_tab\" | \"custom_tab\";\n\ntype ColorMode = \"light\" | \"dark\" | \"auto\";\n// Combined Auth and Session Service\ninterface AuthSessionService {\n // TODO DK NOTES: Should be in BrowserAuthSessionService, not relevant on backend\n loadAuthorizationUrl(\n authorizationURL: string,\n displayMode: DisplayMode,\n ): void;\n // TODO DK NOTES: overrideDisplayMode parameter not appropriate here - also - do we need both this and the above in the interface?\n getAuthorizationUrl(\n scopes: string[],\n overrideDisplayMode: DisplayMode,\n nonce?: string,\n ): Promise<string>;\n // TODO DK NOTES: display mode should be in browser version only. Also, do we need this and the above two in the top-level interface?\n signIn(\n displayMode: DisplayMode,\n scopes: string[],\n nonce?: string,\n ): Promise<void>;\n // TODO DK NOTES: Input should be an auth code - do not assume it comes via an url\n tokenExchange(responseUrl: string): Promise<SessionData>;\n // TODO DK NOTES: Should be async for flexibility\n getSessionData(): SessionData;\n // TODO DK NOTES: Should be async for flexibility\n updateSessionData(data: SessionData): void;\n getUserInfoService(): Promise<UserInfoService>;\n}\n\n// Token Service\ninterface TokenService {\n exchangeCodeForTokens(authCode: string): Promise<Tokens>;\n validateIdToken(idToken: string, nonce: string): boolean;\n refreshAccessToken(refreshToken: string): Promise<Tokens>;\n}\n\n// User Info Service\ninterface UserInfoService {\n getUserInfo<T extends UnknownObject>(\n accessToken: string,\n idToken: string | null,\n ): Promise<User<T> | null>;\n}\n\n// Resource Service\ninterface ResourceService {\n getProtectedResource(accessToken: string): Promise<unknown>;\n}\n\n// Auth Request (for internal use in AuthSessionService)\ntype AuthRequest = {\n clientId: string;\n redirectUri: string;\n state: string;\n nonce: string;\n scope: string;\n};\n\ntype Endpoints = {\n jwks: string;\n auth: string;\n token: string;\n userinfo: string;\n challenge?: string;\n endsession: string;\n};\n\ntype Config = {\n oauthServer: string;\n endpoints?: Endpoints;\n};\n\ntype SessionData = {\n authenticated: boolean; // TODO can this be inferred from the presence of the tokens?\n state?: string;\n accessToken?: string;\n refreshToken?: string;\n idToken?: string;\n
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,MAAM,CAAN,IAAY,UAMX;AAND,WAAY,UAAU;IACpB,6CAA+B,CAAA;IAC/B,iDAAmC,CAAA;IACnC,+CAAiC,CAAA;IACjC,6BAAe,CAAA;IACf,yCAA2B,CAAA;AAC7B,CAAC,EANW,UAAU,KAAV,UAAU,QAMrB;AAsID,MAAM,SAAS,GAAG;IAChB,KAAK;IACL,SAAS;IACT,aAAa;IACb,cAAc;IACd,iBAAiB;CACT,CAAC;AAsGX,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import type { JWTPayload } from \"jose\";\n\ntype UnknownObject = Record<string, unknown>;\ntype EmptyObject = Record<string, never>;\n\nexport enum AuthStatus {\n AUTHENTICATED = \"authenticated\",\n UNAUTHENTICATED = \"unauthenticated\",\n AUTHENTICATING = \"authenticating\",\n ERROR = \"error\",\n SIGNING_OUT = \"signing_out\",\n}\n// Display modes for the auth flow\ntype DisplayMode = \"iframe\" | \"redirect\" | \"new_tab\" | \"custom_tab\";\n\ntype ColorMode = \"light\" | \"dark\" | \"auto\";\n// Combined Auth and Session Service\ninterface AuthSessionService {\n // TODO DK NOTES: Should be in BrowserAuthSessionService, not relevant on backend\n loadAuthorizationUrl(\n authorizationURL: string,\n displayMode: DisplayMode,\n ): void;\n // TODO DK NOTES: overrideDisplayMode parameter not appropriate here - also - do we need both this and the above in the interface?\n getAuthorizationUrl(\n scopes: string[],\n overrideDisplayMode: DisplayMode,\n nonce?: string,\n ): Promise<string>;\n // TODO DK NOTES: display mode should be in browser version only. Also, do we need this and the above two in the top-level interface?\n signIn(\n displayMode: DisplayMode,\n scopes: string[],\n nonce?: string,\n ): Promise<void>;\n // TODO DK NOTES: Input should be an auth code - do not assume it comes via an url\n tokenExchange(responseUrl: string): Promise<SessionData>;\n // TODO DK NOTES: Should be async for flexibility\n getSessionData(): SessionData;\n // TODO DK NOTES: Should be async for flexibility\n updateSessionData(data: SessionData): void;\n getUserInfoService(): Promise<UserInfoService>;\n}\n\n// Token Service\ninterface TokenService {\n exchangeCodeForTokens(authCode: string): Promise<Tokens>;\n validateIdToken(idToken: string, nonce: string): boolean;\n refreshAccessToken(refreshToken: string): Promise<Tokens>;\n}\n\n// User Info Service\ninterface UserInfoService {\n getUserInfo<T extends UnknownObject>(\n accessToken: string,\n idToken: string | null,\n ): Promise<User<T> | null>;\n}\n\n// Resource Service\ninterface ResourceService {\n getProtectedResource(accessToken: string): Promise<unknown>;\n}\n\n// Auth Request (for internal use in AuthSessionService)\ntype AuthRequest = {\n clientId: string;\n redirectUri: string;\n state: string;\n nonce: string;\n scope: string;\n};\n\ntype Endpoints = {\n jwks: string;\n auth: string;\n token: string;\n userinfo: string;\n challenge?: string;\n endsession: string;\n};\n\ntype Config = {\n oauthServer: string;\n endpoints?: Endpoints;\n};\n\ntype SessionData = {\n authenticated: boolean; // TODO can this be inferred from the presence of the tokens?\n state?: string;\n accessToken?: string;\n refreshToken?: string;\n idToken?: string;\n oidcSessionExpiresAt?: number;\n codeVerifier?: string;\n displayMode?: DisplayMode;\n openerUrl?: string;\n};\n\ntype OIDCTokenResponseBody = {\n id_token: string;\n access_token?: string; // Access token is now optional\n oidc_session_expires_at?: number;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n scope?: string;\n};\n\ntype ParsedTokens = {\n id_token: JWTPayload;\n access_token?: JWTPayload;\n refresh_token?: string;\n};\n\n// The format we expose to the frontend via hooks\ntype ForwardedTokens = Record<\n string,\n {\n idToken?: string;\n accessToken?: string;\n refreshToken?: string;\n }\n>;\n\n// The format in the JWT payload\ntype ForwardedTokensJWT = Record<\n string,\n {\n id_token?: string;\n access_token?: string;\n refresh_token?: string;\n scope?: string;\n }\n>;\n\ntype IdTokenPayload = JWTPayload & {\n forwardedTokens?: ForwardedTokensJWT;\n email?: string;\n name?: string;\n picture?: string;\n nonce: string;\n at_hash: string;\n};\n\nconst tokenKeys = [\n \"sub\",\n \"idToken\",\n \"accessToken\",\n \"refreshToken\",\n \"forwardedTokens\",\n] as const;\n\nexport type OAuthTokens = {\n idToken?: string;\n accessToken?: string;\n refreshToken?: string;\n};\n// Derive the Tokens type from the array\ntype Tokens = {\n [K in (typeof tokenKeys)[number]]: K extends \"forwardedTokens\"\n ? ForwardedTokens\n : string;\n};\n\n// Base user interface\ntype BaseUser = {\n id: string;\n email?: string;\n username?: string;\n name?: string;\n given_name?: string;\n family_name?: string;\n picture?: string;\n updated_at?: Date;\n};\n\ntype User<T extends UnknownObject | EmptyObject = EmptyObject> =\n T extends EmptyObject ? BaseUser : BaseUser & T;\n\ntype OpenIdConfiguration = {\n authorization_endpoint: string;\n claims_parameter_supported: boolean;\n claims_supported: string[];\n code_challenge_methods_supported: string[];\n end_session_endpoint: string;\n grant_types_supported: string[];\n issuer: string;\n jwks_uri: string;\n authorization_response_iss_parameter_supported: boolean;\n response_modes_supported: string[];\n response_types_supported: string[];\n scopes_supported: string[];\n subject_types_supported: string[];\n token_endpoint_auth_methods_supported: string[];\n token_endpoint_auth_signing_alg_values_supported: string[];\n token_endpoint: string;\n id_token_signing_alg_values_supported: string[];\n pushed_authorization_request_endpoint: string;\n request_parameter_supported: boolean;\n request_uri_parameter_supported: boolean;\n userinfo_endpoint: string;\n claim_types_supported: string[];\n};\n\ntype LoginPostMessage = {\n source: string;\n type: string;\n clientId: string;\n data:\n | {\n url: string;\n }\n | LoginAppDesignOptions;\n};\n\nexport type IframeAuthMessage = {\n source: \"civicloginApp\";\n type: \"auth_error\" | \"auth_error_try_again\";\n clientId: string;\n data: {\n url?: string;\n error?: string;\n };\n};\n\nexport type LoginAppDesignOptions = {\n colorMode: ColorMode;\n};\nexport type {\n LoginPostMessage,\n AuthSessionService,\n TokenService,\n UserInfoService,\n ResourceService,\n AuthRequest,\n Tokens,\n Endpoints,\n Config,\n SessionData,\n OIDCTokenResponseBody,\n ParsedTokens,\n BaseUser,\n User,\n DisplayMode,\n UnknownObject,\n EmptyObject,\n ForwardedTokens,\n ForwardedTokensJWT,\n IdTokenPayload,\n OpenIdConfiguration,\n ColorMode,\n};\nexport { tokenKeys };\nexport interface AuthStorage {\n get(key: string): Promise<string | null>;\n set(key: string, value: string): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\nexport type IframeMode = \"embedded\" | \"modal\";\n"]}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AuthStatus } from "./types.js";
|
|
1
2
|
/**
|
|
2
3
|
* Checks if a popup window is blocked by the browser.
|
|
3
4
|
*
|
|
@@ -11,5 +12,12 @@ type WithoutUndefined<T> = {
|
|
|
11
12
|
[K in keyof T as undefined extends T[K] ? never : K]: T[K];
|
|
12
13
|
};
|
|
13
14
|
export declare const withoutUndefined: <T extends { [K in keyof T]: unknown; }>(obj: T) => WithoutUndefined<T>;
|
|
15
|
+
/**
|
|
16
|
+
* Converts a string status to AuthStatus enum.
|
|
17
|
+
*
|
|
18
|
+
* @param status - The string status to convert
|
|
19
|
+
* @returns {AuthStatus} - The corresponding AuthStatus enum value
|
|
20
|
+
*/
|
|
21
|
+
export declare const convertToAuthStatus: (status: string) => AuthStatus;
|
|
14
22
|
export {};
|
|
15
23
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,QAAO,OAsBjC,CAAC;AAOF,KAAK,gBAAgB,CAAC,CAAC,IAAI;KACxB,CAAC,IAAI,MAAM,CAAC,IAAI,SAAS,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAC3D,CAAC;AACF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,GAAE,OAC/D,CAAC,KACL,gBAAgB,CAAC,CAAC,CAapB,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,QAAO,OAsBjC,CAAC;AAOF,KAAK,gBAAgB,CAAC,CAAC,IAAI;KACxB,CAAC,IAAI,MAAM,CAAC,IAAI,SAAS,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAC3D,CAAC;AACF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,GAAE,OAC/D,CAAC,KACL,gBAAgB,CAAC,CAAC,CAapB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,WAAY,MAAM,KAAG,UAepD,CAAC"}
|
package/dist/utils.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AuthStatus } from "./types.js";
|
|
1
2
|
/**
|
|
2
3
|
* Checks if a popup window is blocked by the browser.
|
|
3
4
|
*
|
|
@@ -39,4 +40,26 @@ export const withoutUndefined = (obj) => {
|
|
|
39
40
|
}
|
|
40
41
|
return result;
|
|
41
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* Converts a string status to AuthStatus enum.
|
|
45
|
+
*
|
|
46
|
+
* @param status - The string status to convert
|
|
47
|
+
* @returns {AuthStatus} - The corresponding AuthStatus enum value
|
|
48
|
+
*/
|
|
49
|
+
export const convertToAuthStatus = (status) => {
|
|
50
|
+
switch (status) {
|
|
51
|
+
case "authenticated":
|
|
52
|
+
return AuthStatus.AUTHENTICATED;
|
|
53
|
+
case "unauthenticated":
|
|
54
|
+
return AuthStatus.UNAUTHENTICATED;
|
|
55
|
+
case "authenticating":
|
|
56
|
+
return AuthStatus.AUTHENTICATING;
|
|
57
|
+
case "error":
|
|
58
|
+
return AuthStatus.ERROR;
|
|
59
|
+
case "signing_out":
|
|
60
|
+
return AuthStatus.SIGNING_OUT;
|
|
61
|
+
default:
|
|
62
|
+
return AuthStatus.UNAUTHENTICATED;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
42
65
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAY,EAAE;IAC1C,wFAAwF;IACxF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAEtD,6DAA6D;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,gEAAgE;QAChE,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAUF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,GAAM,EACe,EAAE;IACvB,MAAM,MAAM,GAAG,EAAyB,CAAC;IAEzC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC3B,4EAA4E;YAC5E,6BAA6B;YAC7B,8DAA8D;YAC7D,MAAc,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC","sourcesContent":["/**\n * Checks if a popup window is blocked by the browser.\n *\n * This function attempts to open a small popup window and then checks if it was successfully created.\n * If the popup is blocked by the browser, the function returns `true`. Otherwise, it returns `false`.\n *\n * @returns {boolean} - `true` if the popup is blocked, `false` otherwise.\n */\nexport const isPopupBlocked = (): boolean => {\n // First we try to open a small popup window. It either returns a window object or null.\n const popup = window.open(\"\", \"\", \"width=1,height=1\");\n\n // If window.open() returns null, popup is definitely blocked\n if (!popup) {\n return true;\n }\n\n try {\n // Try to access a property of the popup to check if it's usable\n if (typeof popup.closed === \"undefined\") {\n throw new Error(\"Popup is blocked\");\n }\n } catch {\n // Accessing the popup's properties throws an error if the popup is blocked\n return true;\n }\n\n // Close the popup immediately if it was opened\n popup.close();\n return false;\n};\n\n// This type narrows T as far as it can by:\n// - removing all keys where the value is `undefined`\n// - making keys that are not undefined required\n// So, for example: given { a: string | undefined, b: string | undefined },\n// if you pass in { a: \"foo\" }, it returns an object of type: { a: string }\ntype WithoutUndefined<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K];\n};\nexport const withoutUndefined = <T extends { [K in keyof T]: unknown }>(\n obj: T,\n): WithoutUndefined<T> => {\n const result = {} as WithoutUndefined<T>;\n\n for (const key in obj) {\n if (obj[key] !== undefined) {\n // TypeScript needs assurance that key is a valid key in WithoutUndefined<T>\n // We use type assertion here\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (result as any)[key] = obj[key];\n }\n }\n\n return result;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAY,EAAE;IAC1C,wFAAwF;IACxF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAEtD,6DAA6D;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,gEAAgE;QAChE,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAUF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,GAAM,EACe,EAAE;IACvB,MAAM,MAAM,GAAG,EAAyB,CAAC;IAEzC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC3B,4EAA4E;YAC5E,6BAA6B;YAC7B,8DAA8D;YAC7D,MAAc,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAc,EAAE;IAChE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,eAAe;YAClB,OAAO,UAAU,CAAC,aAAa,CAAC;QAClC,KAAK,iBAAiB;YACpB,OAAO,UAAU,CAAC,eAAe,CAAC;QACpC,KAAK,gBAAgB;YACnB,OAAO,UAAU,CAAC,cAAc,CAAC;QACnC,KAAK,OAAO;YACV,OAAO,UAAU,CAAC,KAAK,CAAC;QAC1B,KAAK,aAAa;YAChB,OAAO,UAAU,CAAC,WAAW,CAAC;QAChC;YACE,OAAO,UAAU,CAAC,eAAe,CAAC;IACtC,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { AuthStatus } from \"./types.js\";\n\n/**\n * Checks if a popup window is blocked by the browser.\n *\n * This function attempts to open a small popup window and then checks if it was successfully created.\n * If the popup is blocked by the browser, the function returns `true`. Otherwise, it returns `false`.\n *\n * @returns {boolean} - `true` if the popup is blocked, `false` otherwise.\n */\nexport const isPopupBlocked = (): boolean => {\n // First we try to open a small popup window. It either returns a window object or null.\n const popup = window.open(\"\", \"\", \"width=1,height=1\");\n\n // If window.open() returns null, popup is definitely blocked\n if (!popup) {\n return true;\n }\n\n try {\n // Try to access a property of the popup to check if it's usable\n if (typeof popup.closed === \"undefined\") {\n throw new Error(\"Popup is blocked\");\n }\n } catch {\n // Accessing the popup's properties throws an error if the popup is blocked\n return true;\n }\n\n // Close the popup immediately if it was opened\n popup.close();\n return false;\n};\n\n// This type narrows T as far as it can by:\n// - removing all keys where the value is `undefined`\n// - making keys that are not undefined required\n// So, for example: given { a: string | undefined, b: string | undefined },\n// if you pass in { a: \"foo\" }, it returns an object of type: { a: string }\ntype WithoutUndefined<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K];\n};\nexport const withoutUndefined = <T extends { [K in keyof T]: unknown }>(\n obj: T,\n): WithoutUndefined<T> => {\n const result = {} as WithoutUndefined<T>;\n\n for (const key in obj) {\n if (obj[key] !== undefined) {\n // TypeScript needs assurance that key is a valid key in WithoutUndefined<T>\n // We use type assertion here\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (result as any)[key] = obj[key];\n }\n }\n\n return result;\n};\n\n/**\n * Converts a string status to AuthStatus enum.\n *\n * @param status - The string status to convert\n * @returns {AuthStatus} - The corresponding AuthStatus enum value\n */\nexport const convertToAuthStatus = (status: string): AuthStatus => {\n switch (status) {\n case \"authenticated\":\n return AuthStatus.AUTHENTICATED;\n case \"unauthenticated\":\n return AuthStatus.UNAUTHENTICATED;\n case \"authenticating\":\n return AuthStatus.AUTHENTICATING;\n case \"error\":\n return AuthStatus.ERROR;\n case \"signing_out\":\n return AuthStatus.SIGNING_OUT;\n default:\n return AuthStatus.UNAUTHENTICATED;\n }\n};\n"]}
|
|
@@ -41,6 +41,8 @@ export declare class CivicAuth {
|
|
|
41
41
|
* clientId: "your-client-id",
|
|
42
42
|
* // redirectUrl is optional - defaults to current page (window.location.origin + window.location.pathname)
|
|
43
43
|
* redirectUrl: "https://your-app.com/callback", // optional
|
|
44
|
+
* // logoutRedirectUrl is optional - defaults to redirectUrl if not provided
|
|
45
|
+
* logoutRedirectUrl: "https://your-app.com/logout", // optional
|
|
44
46
|
* // oauthServerBaseUrl is optional - defaults to "https://auth.civic.com/oauth"
|
|
45
47
|
* oauthServerBaseUrl: "https://auth-server.com/", // optional
|
|
46
48
|
* // scopes is optional - defaults to ['openid', 'profile', 'email', 'offline_access']
|
|
@@ -119,6 +121,11 @@ export declare class CivicAuth {
|
|
|
119
121
|
* Get the current session
|
|
120
122
|
*/
|
|
121
123
|
getCurrentSession(): Promise<Session | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Get current session tokens including decoded forwarded tokens
|
|
126
|
+
* This method extracts and decodes forwarded tokens from the ID token JWT
|
|
127
|
+
*/
|
|
128
|
+
getTokensWithForwardedTokens(): Promise<import("../utils/auth-utils.js").ExtractedTokens>;
|
|
122
129
|
/**
|
|
123
130
|
* Check if user is authenticated
|
|
124
131
|
*/
|
|
@@ -161,6 +168,11 @@ export declare class CivicAuth {
|
|
|
161
168
|
* Handle logout
|
|
162
169
|
*/
|
|
163
170
|
logout(): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Handle logout state cleanup
|
|
173
|
+
* This mirrors the logic from useSignIn.ts to properly clean up after logout
|
|
174
|
+
*/
|
|
175
|
+
private handleLogoutStateCleanup;
|
|
164
176
|
}
|
|
165
177
|
export type { CivicAuthClientConfig } from "./types/AuthTypes.js";
|
|
166
178
|
export { CivicAuthErrorCode } from "./types/AuthTypes.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CivicAuth.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/auth/CivicAuth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"CivicAuth.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/auth/CivicAuth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAsB7D,OAAO,KAAK,EACV,qBAAqB,EAEtB,MAAM,sBAAsB,CAAC;AAW9B;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,kBAAkB,CAKT;IAGjB,OAAO,CAAC,WAAW,CAAC,CAAsB;IAC1C,OAAO,CAAC,kBAAkB,CAAC,CAA8B;IACzD,OAAO,CAAC,iBAAiB,CAAC,CAA2B;IACrD,OAAO,CAAC,wBAAwB,CAAC,CAAS;IAC1C,OAAO,CAAC,yBAAyB,CAAC,CAAS;IAC3C,OAAO,CAAC,cAAc,CAAkB;IAGxC,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,iBAAiB,CAAC,CAAoB;IAE9C;;;OAGG;IACH,OAAO;IAiCP;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;WACiB,MAAM,CACxB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,SAAS,CAAC;IAMrB;;OAEG;YACW,IAAI;IAgElB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;OAEG;YACW,YAAY;IA4B1B;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC;IA8ChD;;OAEG;YACW,iCAAiC;IA6C/C;;OAEG;YACW,4BAA4B;IA6C1C;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA4ClC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiC1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA6C/B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAehC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;OAEG;YACW,cAAc;IA6D5B;;OAEG;IACI,OAAO,IAAI,IAAI;IA6BtB;;OAEG;IACU,iBAAiB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAIzD;;;OAGG;IACU,4BAA4B;IAKzC;;OAEG;IACU,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhD;;OAEG;IACU,cAAc;IAI3B;;OAEG;IACU,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI1C;;OAEG;IACU,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3C;;OAEG;IACI,sBAAsB;;;;;IAI7B;;;OAGG;IACI,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI;IAK7D;;;OAGG;IACI,oBAAoB,IAAI,OAAO,GAAG,UAAU,GAAG,SAAS;IAI/D;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrC;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IA2EpC;;;OAGG;YACW,wBAAwB;CAsEvC;AAGD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AuthEvent } from "../types/index.js";
|
|
2
|
-
import { buildAuthUrl } from "../utils/auth-utils.js";
|
|
2
|
+
import { buildAuthUrl, extractTokensFromSession } from "../utils/auth-utils.js";
|
|
3
3
|
import { createMainLogger, configureLogging, setCurrentLogger, } from "../utils/logger.js";
|
|
4
4
|
import { GenericPublicClientPKCEProducer } from "../../services/PKCE.js";
|
|
5
5
|
import { generateState } from "../../lib/oauth.js";
|
|
@@ -8,6 +8,7 @@ import { AuthenticationEvents } from "./AuthenticationEvents.js";
|
|
|
8
8
|
import { PopupError } from "../../services/types.js";
|
|
9
9
|
import { handleOAuthRedirectPage } from "./handlers/OAuthCallbackHandler.js";
|
|
10
10
|
import { generateOauthLogoutUrl, clearTokens, retrieveTokens, } from "../../shared/lib/util.js";
|
|
11
|
+
import { LOGOUT_STATE } from "../../constants.js";
|
|
11
12
|
import { getOauthEndpoints } from "../../lib/oauth.js";
|
|
12
13
|
import { CivicAuthError, CivicAuthErrorCode, CIVIC_AUTH_CONSTANTS, } from "./types/AuthTypes.js";
|
|
13
14
|
import { processConfigWithDefaults } from "./config/ConfigProcessor.js";
|
|
@@ -83,6 +84,8 @@ export class CivicAuth {
|
|
|
83
84
|
* clientId: "your-client-id",
|
|
84
85
|
* // redirectUrl is optional - defaults to current page (window.location.origin + window.location.pathname)
|
|
85
86
|
* redirectUrl: "https://your-app.com/callback", // optional
|
|
87
|
+
* // logoutRedirectUrl is optional - defaults to redirectUrl if not provided
|
|
88
|
+
* logoutRedirectUrl: "https://your-app.com/logout", // optional
|
|
86
89
|
* // oauthServerBaseUrl is optional - defaults to "https://auth.civic.com/oauth"
|
|
87
90
|
* oauthServerBaseUrl: "https://auth-server.com/", // optional
|
|
88
91
|
* // scopes is optional - defaults to ['openid', 'profile', 'email', 'offline_access']
|
|
@@ -134,6 +137,8 @@ export class CivicAuth {
|
|
|
134
137
|
currentUrl: window.location.href,
|
|
135
138
|
redirectUrl: this.config.redirectUrl,
|
|
136
139
|
});
|
|
140
|
+
// Handle logout state cleanup first (before processing auth callbacks)
|
|
141
|
+
await this.handleLogoutStateCleanup();
|
|
137
142
|
if (isCallbackPage) {
|
|
138
143
|
this.logger.info("๐ Processing callback page");
|
|
139
144
|
await this.handleCallback();
|
|
@@ -549,6 +554,14 @@ export class CivicAuth {
|
|
|
549
554
|
async getCurrentSession() {
|
|
550
555
|
return this.sessionManager.getCurrentSession() || null;
|
|
551
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Get current session tokens including decoded forwarded tokens
|
|
559
|
+
* This method extracts and decodes forwarded tokens from the ID token JWT
|
|
560
|
+
*/
|
|
561
|
+
async getTokensWithForwardedTokens() {
|
|
562
|
+
const session = await this.getCurrentSession();
|
|
563
|
+
return extractTokensFromSession(session);
|
|
564
|
+
}
|
|
552
565
|
/**
|
|
553
566
|
* Check if user is authenticated
|
|
554
567
|
*/
|
|
@@ -629,10 +642,18 @@ export class CivicAuth {
|
|
|
629
642
|
const state = generateState({
|
|
630
643
|
displayMode: this.config.displayMode || "iframe",
|
|
631
644
|
});
|
|
645
|
+
this.logger.info("๐ Storing logout state", {
|
|
646
|
+
generatedState: state,
|
|
647
|
+
logoutStateKey: LOGOUT_STATE,
|
|
648
|
+
displayMode: this.config.displayMode,
|
|
649
|
+
});
|
|
650
|
+
// Store logout state for cleanup after redirect
|
|
651
|
+
// This matches the React implementation - only store state for redirect flow
|
|
652
|
+
await this.storage.set(LOGOUT_STATE, state);
|
|
632
653
|
// Generate logout URL
|
|
633
654
|
const logoutUrl = await generateOauthLogoutUrl({
|
|
634
655
|
clientId: this.config.clientId,
|
|
635
|
-
redirectUrl: this.config.
|
|
656
|
+
redirectUrl: this.config.logoutRedirectUrl,
|
|
636
657
|
idToken: tokens.id_token,
|
|
637
658
|
state: state,
|
|
638
659
|
oauthServer: this.config.oauthServerBaseUrl,
|
|
@@ -640,9 +661,8 @@ export class CivicAuth {
|
|
|
640
661
|
this.logger.info("๐ Generated logout URL", {
|
|
641
662
|
logoutUrl: logoutUrl.toString(),
|
|
642
663
|
});
|
|
643
|
-
// Clear local tokens and session
|
|
644
|
-
await
|
|
645
|
-
await this.sessionManager.clearSession();
|
|
664
|
+
// Clear local tokens and session but NOT the logout state (needed for cleanup after redirect)
|
|
665
|
+
await this.sessionManager.clearSession(true); // preserveLogoutState = true
|
|
646
666
|
// Emit logout complete event before redirect
|
|
647
667
|
this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {
|
|
648
668
|
detail: "Logout successful",
|
|
@@ -659,6 +679,69 @@ export class CivicAuth {
|
|
|
659
679
|
throw new CivicAuthError("Logout failed", CivicAuthErrorCode.LOGOUT_FAILED);
|
|
660
680
|
}
|
|
661
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* Handle logout state cleanup
|
|
684
|
+
* This mirrors the logic from useSignIn.ts to properly clean up after logout
|
|
685
|
+
*/
|
|
686
|
+
async handleLogoutStateCleanup() {
|
|
687
|
+
try {
|
|
688
|
+
const params = new URLSearchParams(window.location.search);
|
|
689
|
+
const state = params.get("state");
|
|
690
|
+
this.logger.info("๐ Checking for logout state cleanup", {
|
|
691
|
+
currentUrl: window.location.href,
|
|
692
|
+
hasStateParam: !!state,
|
|
693
|
+
stateValue: state,
|
|
694
|
+
rawSearch: window.location.search,
|
|
695
|
+
});
|
|
696
|
+
if (!state) {
|
|
697
|
+
this.logger.info("๐ No state parameter found, skipping logout cleanup");
|
|
698
|
+
return; // No state parameter, nothing to cleanup
|
|
699
|
+
}
|
|
700
|
+
// Check if we have a stored logout state that matches
|
|
701
|
+
const storedLogoutState = await this.storage.get(LOGOUT_STATE);
|
|
702
|
+
// The state might be URL-decoded by URLSearchParams, but stored as plain
|
|
703
|
+
// Let's try both the decoded and encoded versions
|
|
704
|
+
const decodedState = decodeURIComponent(state);
|
|
705
|
+
this.logger.info("๐ Comparing logout states", {
|
|
706
|
+
urlState: state,
|
|
707
|
+
decodedState,
|
|
708
|
+
storedLogoutState,
|
|
709
|
+
directMatch: state === storedLogoutState,
|
|
710
|
+
decodedMatch: decodedState === storedLogoutState,
|
|
711
|
+
});
|
|
712
|
+
if (state === storedLogoutState || decodedState === storedLogoutState) {
|
|
713
|
+
this.logger.info("๐งน Cleaning up logout state", {
|
|
714
|
+
state,
|
|
715
|
+
storedLogoutState,
|
|
716
|
+
});
|
|
717
|
+
// Clear tokens and user data from storage
|
|
718
|
+
await clearTokens(this.storage);
|
|
719
|
+
await this.sessionManager.clearSession();
|
|
720
|
+
// Clean up the logout state from storage
|
|
721
|
+
await this.storage.delete(LOGOUT_STATE);
|
|
722
|
+
// Emit logout complete event
|
|
723
|
+
this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {
|
|
724
|
+
detail: "Logout cleanup completed",
|
|
725
|
+
});
|
|
726
|
+
// Clean up URL by removing query parameters
|
|
727
|
+
const cleanUrl = window.location.href.split("?")[0];
|
|
728
|
+
window.history.replaceState({}, document.title, cleanUrl);
|
|
729
|
+
this.logger.info("โ
Logout state cleanup completed", {
|
|
730
|
+
cleanUrl,
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
this.logger.info("๐ Logout states don't match, skipping cleanup", {
|
|
735
|
+
urlState: state,
|
|
736
|
+
storedLogoutState,
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
catch (error) {
|
|
741
|
+
this.logger.warn("โ ๏ธ Error during logout state cleanup", { error });
|
|
742
|
+
// Don't throw error to prevent initialization failure
|
|
743
|
+
}
|
|
744
|
+
}
|
|
662
745
|
}
|
|
663
746
|
export { CivicAuthErrorCode } from "./types/AuthTypes.js";
|
|
664
747
|
//# sourceMappingURL=CivicAuth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CivicAuth.js","sourceRoot":"","sources":["../../../src/vanillajs/auth/CivicAuth.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../types/index.js\";\nimport type { Endpoints, AuthStorage } from \"../../types.js\";\nimport { buildAuthUrl } from \"../utils/auth-utils.js\";\nimport type { AuthResult, Session } from \"../types/index.js\";\nimport type { createLogger } from \"../utils/logger.js\";\nimport {\n createMainLogger,\n configureLogging,\n setCurrentLogger,\n} from \"../utils/logger.js\";\nimport { GenericPublicClientPKCEProducer } from \"../../services/PKCE.js\";\nimport { generateState } from \"../../lib/oauth.js\";\nimport { SessionManager } from \"./SessionManager.js\";\nimport { AuthenticationEvents } from \"./AuthenticationEvents.js\";\nimport { PopupError } from \"../../services/types.js\";\nimport { handleOAuthRedirectPage } from \"./handlers/OAuthCallbackHandler.js\";\nimport {\n generateOauthLogoutUrl,\n clearTokens,\n retrieveTokens,\n} from \"../../shared/lib/util.js\";\nimport { getOauthEndpoints } from \"../../lib/oauth.js\";\n\n// Import new modular components\nimport type {\n CivicAuthClientConfig,\n ProcessedCivicAuthConfig,\n} from \"./types/AuthTypes.js\";\nimport {\n CivicAuthError,\n CivicAuthErrorCode,\n CIVIC_AUTH_CONSTANTS,\n} from \"./types/AuthTypes.js\";\nimport { processConfigWithDefaults } from \"./config/ConfigProcessor.js\";\nimport { MessageHandler } from \"./handlers/MessageHandler.js\";\nimport { PopupHandler } from \"./handlers/PopupHandler.js\";\nimport { IframeAuthHandler } from \"./handlers/IframeAuthHandler.js\";\n\n/**\n * CivicAuth client for handling OAuth authentication\n *\n * This is a refactored version that uses a modular architecture for better maintainability.\n */\nexport class CivicAuth {\n private config: ProcessedCivicAuthConfig;\n private storage: AuthStorage;\n private endpoints?: Endpoints;\n private logger: ReturnType<typeof createLogger>;\n private sessionManager: SessionManager;\n private events: AuthenticationEvents;\n private initialDisplayMode:\n | \"iframe\"\n | \"modal\"\n | \"redirect\"\n | \"new_tab\"\n | \"custom_tab\";\n\n // Authentication state\n private authPromise?: Promise<AuthResult>;\n private authPromiseResolve?: (value: AuthResult) => void;\n private authPromiseReject?: (reason?: Error) => void;\n private authProcessTimeoutHandle?: number;\n private popupFailureTimeoutHandle?: number;\n private hasPopupFailed: boolean = false;\n\n // Handlers\n private messageHandler?: MessageHandler;\n private popupHandler?: PopupHandler;\n private iframeAuthHandler?: IframeAuthHandler;\n\n /**\n * Private constructor - initializes configuration and handlers.\n * Use {@link CivicAuth.create} to create a new instance.\n */\n private constructor(config: CivicAuthClientConfig) {\n // Process config with defaults and validation\n this.config = processConfigWithDefaults(config);\n this.initialDisplayMode = this.config.displayMode;\n\n // Configure logging\n configureLogging(this.config.logging);\n\n // Initialize logger - always use \"vanillajs\" as base namespace\n if (this.config.logging?.enabled) {\n this.logger = createMainLogger(\"vanillajs\"); // Always use \"vanillajs\"\n } else {\n this.logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n setCurrentLogger(this.logger);\n this.storage = this.config.storageAdapter;\n\n // Always initialize events - use provided events or create default instance\n this.events = config.events || new AuthenticationEvents();\n\n // Always initialize SessionManager\n this.sessionManager = new SessionManager(this.storage, this.events);\n\n // Initialize handlers\n this.initializeHandlers();\n }\n\n /**\n * Creates and initializes a new instance of CivicAuth.\n * This is the recommended way to create a CivicAuth instance.\n *\n * @param config - Configuration options for the auth client\n * @returns A promise that resolves with the initialized CivicAuth instance\n * @throws {CivicAuthError} If initialization fails or required configuration is missing\n *\n * @example\n * ```typescript\n * const auth = await CivicAuth.create({\n * clientId: \"your-client-id\",\n * // redirectUrl is optional - defaults to current page (window.location.origin + window.location.pathname)\n * redirectUrl: \"https://your-app.com/callback\", // optional\n * // oauthServerBaseUrl is optional - defaults to \"https://auth.civic.com/oauth\"\n * oauthServerBaseUrl: \"https://auth-server.com/\", // optional\n * // scopes is optional - defaults to ['openid', 'profile', 'email', 'offline_access']\n * scopes: [\"openid\", \"profile\"], // optional\n * targetContainerElement: \"auth-container\",\n * textSignals: {\n * success: \"Authentication successful!\"\n * }\n * });\n * ```\n */\n public static async create(\n config: CivicAuthClientConfig,\n ): Promise<CivicAuth> {\n const instance = new CivicAuth(config);\n await instance.init();\n return instance;\n }\n\n /**\n * Initializes the auth client and checks for callback handling\n */\n private async init(): Promise<void> {\n this.logger.info(\"๐ Initializing CivicAuth\", {\n currentUrl: window.location.href,\n redirectUrl: this.config.redirectUrl,\n oauthServerBaseUrl: this.config.oauthServerBaseUrl,\n isCallbackUrl: window.location.href.startsWith(this.config.redirectUrl),\n });\n\n try {\n // Get OAuth endpoints using shared function (handles trailing slash automatically)\n this.endpoints = await getOauthEndpoints(this.config.oauthServerBaseUrl);\n\n this.logger.info(\"๐ OAuth endpoints configured\", {\n endpoints: this.endpoints,\n });\n\n // Initialize SessionManager with auth config\n if (this.sessionManager) {\n const authConfig = {\n clientId: this.config.clientId,\n redirectUrl: this.config.redirectUrl,\n oauthServer: this.config.oauthServerBaseUrl,\n scopes: this.config.scopes,\n endpoints: this.endpoints,\n };\n this.logger.info(\"๐ง Initializing SessionManager\", { authConfig });\n await this.sessionManager.initializeWithAuthConfig(authConfig);\n }\n\n // Check if we're on the callback page\n const isCallbackPage = window.location.href.startsWith(\n this.config.redirectUrl,\n );\n this.logger.info(\"๐ Callback page check\", {\n isCallbackPage,\n currentUrl: window.location.href,\n redirectUrl: this.config.redirectUrl,\n });\n\n if (isCallbackPage) {\n this.logger.info(\"๐ Processing callback page\");\n await this.handleCallback();\n } else {\n this.logger.info(\"๐ Not a callback page, initialization complete\");\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? error.message\n : \"Failed to initialize authentication\";\n this.logger.error(\"โ CivicAuth initialization failed\", {\n error: errorMessage,\n stack: error instanceof Error ? error.stack : undefined,\n });\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: errorMessage,\n });\n throw new CivicAuthError(errorMessage, CivicAuthErrorCode.INIT_FAILED);\n }\n }\n\n /**\n * Initialize all handlers with proper configuration\n */\n private initializeHandlers(): void {\n const handlerConfig = {\n config: this.config,\n logger: this.logger,\n onAuthSuccess: this.handleAuthSuccess.bind(this),\n onAuthError: this.handleAuthError.bind(this),\n cleanup: this.cleanup.bind(this),\n };\n\n this.messageHandler = new MessageHandler({\n ...handlerConfig,\n onPopupFailure: this.handlePopupFailure.bind(this),\n });\n\n this.popupHandler = new PopupHandler(handlerConfig);\n\n this.iframeAuthHandler = new IframeAuthHandler({\n ...handlerConfig,\n messageHandler: this.messageHandler.handleMessage,\n });\n }\n\n /**\n * Builds the authentication URL with PKCE challenge\n */\n private async buildAuthUrl(): Promise<string> {\n if (!this.endpoints) {\n throw new CivicAuthError(\n \"OAuth endpoints not initialized. Please wait for initialization to complete.\",\n CivicAuthErrorCode.ENDPOINTS_NOT_INITIALIZED,\n );\n }\n\n const pkceProducer = new GenericPublicClientPKCEProducer(this.storage);\n const codeChallenge = await pkceProducer.getCodeChallenge();\n const state =\n this.config.initialState ||\n generateState({\n displayMode: this.config.displayMode || \"iframe\",\n });\n\n return buildAuthUrl({\n endpoints: this.endpoints,\n clientId: this.config.clientId,\n redirectUrl: this.config.redirectUrl,\n scopes: this.config.scopes,\n codeChallenge,\n state,\n prompt: this.config.prompt,\n nonce: this.config.nonce,\n });\n }\n\n /**\n * Starts the authentication process\n * @returns A promise that resolves with the authentication result\n * @throws {CivicAuthError} If authentication fails or times out\n */\n async startAuthentication(): Promise<AuthResult> {\n this.logger.info(\"๐ฌ Starting authentication process\", {\n displayMode: this.config.displayMode,\n userAgent: navigator.userAgent,\n currentUrl: window.location.href,\n });\n\n if (!this.endpoints) {\n const error = new CivicAuthError(\n \"OAuth endpoints not initialized. Please wait for initialization to complete.\",\n CivicAuthErrorCode.ENDPOINTS_NOT_INITIALIZED,\n );\n this.logger.error(\"โ Endpoints not initialized\", {\n error: error.message,\n });\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: error.message,\n });\n throw error;\n }\n\n if (this.authPromise) {\n this.logger.info(\n \"โณ Authentication already in progress, returning existing promise\",\n );\n return this.authPromise;\n }\n\n const fullAuthUrl = await this.buildAuthUrl();\n this.logger.info(\"๐ Built authentication URL\", {\n url: fullAuthUrl,\n displayMode: this.config.displayMode,\n authProcessTimeout: this.config.authProcessTimeout,\n });\n\n this.authPromise = new Promise<AuthResult>((resolve, reject) => {\n this.authPromiseResolve = resolve;\n this.authPromiseReject = reject;\n\n this.handleAuthenticationByDisplayMode(fullAuthUrl);\n this.setupAuthenticationTimeout();\n });\n\n return this.authPromise;\n }\n\n /**\n * Handle authentication based on display mode\n */\n private async handleAuthenticationByDisplayMode(\n fullAuthUrl: string,\n ): Promise<void> {\n this.logger.info(\"๐ฏ Handling authentication with display mode\", {\n displayMode: this.config.displayMode,\n });\n\n try {\n switch (this.config.displayMode) {\n case \"redirect\":\n this.logger.info(\"๐ Using redirect mode\");\n window.location.href = fullAuthUrl;\n break;\n\n case \"new_tab\":\n this.logger.info(\"๐ฑ Using new_tab mode\");\n if (!this.popupHandler) {\n throw new Error(\"Popup handler not initialized\");\n }\n await this.popupHandler.handleNewTabAuth(fullAuthUrl);\n break;\n\n case \"iframe\":\n default: {\n this.logger.info(\"๐ผ๏ธ Using iframe mode\");\n if (!this.iframeAuthHandler || !this.messageHandler) {\n throw new Error(\"Iframe handler not initialized\");\n }\n const iframeElement =\n await this.iframeAuthHandler.handleIframeAuth(fullAuthUrl);\n this.messageHandler.updateIframeElement(iframeElement);\n break;\n }\n }\n } catch (error) {\n if (error instanceof PopupError) {\n await this.handlePopupErrorWithFallback(fullAuthUrl, error);\n } else {\n this.handleAuthError(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n\n /**\n * Handle popup error with redirect fallback\n */\n private async handlePopupErrorWithFallback(\n fullAuthUrl: string,\n error: PopupError,\n ): Promise<void> {\n this.logger.warn(\"๐ซ Popup failed, falling back to redirect mode\", {\n originalDisplayMode: this.config.displayMode,\n error: error.message,\n });\n\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Popup blocked, falling back to redirect mode\",\n });\n\n try {\n this.logger.info(\"๐ Attempting redirect fallback\");\n\n // Clean up current authentication attempt\n this.cleanup();\n\n // Always switch to redirect mode for Safari compatibility\n this.config.displayMode = \"redirect\";\n\n // Regenerate the auth URL with updated display mode in state\n const fallbackAuthUrl = await this.buildAuthUrl();\n\n this.logger.info(\"๐ Redirecting to auth URL\", { url: fallbackAuthUrl });\n window.location.href = fallbackAuthUrl;\n this.logger.info(\"โ
Redirect initiated successfully\");\n } catch (redirectError) {\n this.logger.error(\"โ Redirect fallback failed\", {\n error: redirectError,\n redirectUrl: fullAuthUrl,\n });\n\n const fallbackError = new CivicAuthError(\n \"Failed to open popup window and redirect fallback failed. Please check your browser's popup settings.\",\n CivicAuthErrorCode.INIT_FAILED,\n );\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: fallbackError.message,\n });\n this.handleAuthError(fallbackError);\n }\n }\n\n /**\n * Setup authentication timeout\n */\n private setupAuthenticationTimeout(): void {\n // Skip timeout for embedded iframe mode - embedded iframes should stay persistent\n if (\n this.config.displayMode === \"iframe\" &&\n this.config.iframeDisplayMode === \"embedded\"\n ) {\n this.logger.debug(\n \"โฐ Skipping authentication timeout for embedded iframe mode\",\n {\n displayMode: this.config.displayMode,\n iframeDisplayMode: this.config.iframeDisplayMode,\n },\n );\n return;\n }\n\n if (this.config.authProcessTimeout && this.config.authProcessTimeout > 0) {\n this.logger.debug(\"โฐ Setting up authentication timeout\", {\n authProcessTimeout: this.config.authProcessTimeout,\n displayMode: this.config.displayMode,\n iframeDisplayMode: this.config.iframeDisplayMode,\n });\n\n this.authProcessTimeoutHandle = window.setTimeout(() => {\n this.logger.error(\"โฐ Authentication timed out\", {\n displayMode: this.config.displayMode,\n iframeDisplayMode: this.config.iframeDisplayMode,\n currentOrigin: window.location.origin,\n authProcessTimeout: this.config.authProcessTimeout,\n });\n\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication timed out\",\n });\n\n const error = new CivicAuthError(\n \"Authentication timed out\",\n CivicAuthErrorCode.AUTH_PROCESS_TIMEOUT,\n );\n this.handleAuthError(error);\n }, this.config.authProcessTimeout);\n }\n }\n\n /**\n * Handle successful authentication\n */\n private handleAuthSuccess(result: AuthResult): void {\n this.logger.info(\"โ
Authentication successful\");\n this.authPromiseResolve?.(result);\n this.cleanup();\n }\n\n /**\n * Handle authentication error\n */\n private handleAuthError(error: Error): void {\n this.logger.error(\"โ Authentication failed\", { error: error.message });\n this.authPromiseReject?.(error);\n this.cleanup();\n }\n\n /**\n * Handle popup failure - simplified like React implementation\n */\n private handlePopupFailure(failedUrl?: string): void {\n this.hasPopupFailed = true;\n\n this.logger.warn(\"Popup failed, using redirect mode instead...\", {\n failedUrl,\n });\n\n // Clean up iframe if it exists\n if (this.iframeAuthHandler) {\n this.iframeAuthHandler.cleanupIframe();\n }\n\n // Always redirect to the failed URL or build a new one\n if (failedUrl) {\n window.location.href = failedUrl;\n } else {\n this.buildAuthUrl()\n .then((authUrl) => {\n window.location.href = authUrl;\n })\n .catch((error) => {\n this.logger.error(\"Failed to build auth URL for redirect fallback\", {\n error,\n });\n const fallbackError = new CivicAuthError(\n \"Failed to redirect for authentication\",\n CivicAuthErrorCode.INIT_FAILED,\n );\n this.handleAuthError(fallbackError);\n });\n }\n }\n\n /**\n * Show popup failure message to user\n */\n private showPopupFailureMessage(\n customMessage: string = \"Authentication will continue in this window. Please wait...\",\n ): void {\n const container = this.getContainerElement();\n if (!container) {\n this.logger.warn(\n \"Cannot show popup failure message - container not found\",\n );\n return;\n }\n const existingMessage = document.getElementById(\n \"civic-auth-popup-failure-message\",\n );\n if (existingMessage && existingMessage.parentNode) {\n existingMessage.parentNode.removeChild(existingMessage);\n }\n const messageOverlay = document.createElement(\"div\");\n messageOverlay.id = \"civic-auth-popup-failure-message\";\n messageOverlay.style.cssText =\n \"position:absolute;top:0;left:0;right:0;background:rgba(255,249,196,.95);border:1px solid #f59e0b;border-radius:6px;padding:12px;margin:8px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;color:#92400e;z-index:1000;box-shadow:0 2px 4px rgba(0,0,0,.1);\";\n messageOverlay.innerHTML =\n '<div style=\"display:flex;align-items:center;gap:8px;\">' +\n '<span style=\"font-size:16px;\">โ ๏ธ</span>' +\n \"<div>\" +\n \"<strong>Popup blocked</strong><br>\" +\n '<span style=\"font-size:12px;\">' +\n customMessage +\n \"</span>\" +\n \"</div>\" +\n \"</div>\";\n\n if (getComputedStyle(container).position === \"static\") {\n container.style.position = \"relative\";\n }\n\n container.appendChild(messageOverlay);\n\n setTimeout(() => {\n if (messageOverlay.parentNode) {\n messageOverlay.parentNode.removeChild(messageOverlay);\n }\n }, 10000);\n this.logger.info(\"Popup failure message displayed to user\");\n }\n\n /**\n * Setup popup failure timeout\n */\n private setupPopupFailureTimeout(): void {\n this.popupFailureTimeoutHandle = window.setTimeout(() => {\n this.logger.info(\"โฐ Popup failure timeout reached\");\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication timeout - popup failure scenario\",\n });\n\n const error = new CivicAuthError(\n \"Authentication timeout - popup failure scenario\",\n CivicAuthErrorCode.AUTH_PROCESS_TIMEOUT,\n );\n this.handleAuthError(error);\n }, 20000); // 20 seconds\n }\n\n /**\n * Gets the container element for the auth iframe\n */\n private getContainerElement(): HTMLElement | null {\n if (typeof this.config.targetContainerElement === \"string\") {\n const element = document.getElementById(\n this.config.targetContainerElement,\n );\n if (!element) {\n this.logger.warn(\n `Container element with ID \"${this.config.targetContainerElement}\" not found`,\n );\n }\n return element;\n }\n return this.config.targetContainerElement ?? null;\n }\n\n /**\n * Handle OAuth callback\n */\n private async handleCallback(): Promise<void> {\n this.logger.info(\"๐ Handling OAuth callback\", {\n currentUrl: window.location.href,\n redirectUrl: this.config.redirectUrl,\n });\n\n try {\n const callbackHandled = await handleOAuthRedirectPage({\n clientId: this.config.clientId,\n oauthServer: this.config.oauthServerBaseUrl,\n redirectUrl: this.config.redirectUrl,\n textSignals: {\n success: this.config.textSignals.success,\n error: this.config.textSignals.error || \"Authentication failed\",\n },\n storageAdapter: this.storage,\n });\n\n this.logger.info(\"๐ Callback processing result\", { callbackHandled });\n\n if (callbackHandled) {\n const successSignal = document.getElementById(\n CIVIC_AUTH_CONSTANTS.SUCCESS_SIGNAL_ID,\n );\n const errorSignal = document.getElementById(\n CIVIC_AUTH_CONSTANTS.ERROR_SIGNAL_ID,\n );\n\n if (successSignal) {\n this.logger.info(\"โ
Success signal found\");\n let userInfo = null;\n const userInfoAttr = successSignal.getAttribute(\"data-user-info\");\n if (userInfoAttr) {\n try {\n userInfo = JSON.parse(userInfoAttr);\n } catch (error) {\n this.logger.error(\"โ Failed to parse user info\", { error });\n }\n }\n this.events.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Callback processed successfully\",\n user: userInfo,\n });\n } else if (errorSignal) {\n this.logger.error(\"โ Error signal found\");\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: errorSignal.textContent || \"Unknown error during callback\",\n });\n }\n }\n } catch (error) {\n this.logger.error(\"โ Callback handling failed\", { error });\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail:\n error instanceof Error\n ? error.message\n : \"Unknown error during callback\",\n });\n }\n }\n\n /**\n * Cleans up resources and event listeners\n */\n public cleanup(): void {\n this.logger.info(\"Cleaning up authentication client\");\n\n // Clean up handlers\n this.iframeAuthHandler?.cleanupIframe();\n\n // Clean up timeouts\n if (this.authProcessTimeoutHandle) {\n window.clearTimeout(this.authProcessTimeoutHandle);\n this.authProcessTimeoutHandle = undefined;\n }\n\n if (this.popupFailureTimeoutHandle) {\n window.clearTimeout(this.popupFailureTimeoutHandle);\n this.popupFailureTimeoutHandle = undefined;\n }\n\n // Reset state\n this.hasPopupFailed = false;\n this.authPromise = undefined;\n this.authPromiseResolve = undefined;\n this.authPromiseReject = undefined;\n\n // Remove message event listener\n if (this.messageHandler) {\n window.removeEventListener(\"message\", this.messageHandler.handleMessage);\n }\n }\n\n /**\n * Get the current session\n */\n public async getCurrentSession(): Promise<Session | null> {\n return this.sessionManager.getCurrentSession() || null;\n }\n\n /**\n * Check if user is authenticated\n */\n public async isAuthenticated(): Promise<boolean> {\n return this.sessionManager.isAuthenticated() || false;\n }\n\n /**\n * Get the current user\n */\n public async getCurrentUser() {\n return this.sessionManager.getCurrentUser() || null;\n }\n\n /**\n * Clear the current session\n */\n public async clearSession(): Promise<void> {\n return this.sessionManager.clearSession();\n }\n\n /**\n * Manually refresh tokens\n */\n public async refreshTokens(): Promise<void> {\n return this.sessionManager.refreshTokens();\n }\n\n /**\n * Get token refresher state for debugging\n */\n public getTokenRefresherState() {\n return this.sessionManager.getTokenRefresherState() || null;\n }\n\n /**\n * Update the iframe display mode\n * @param mode - The display mode to use for the iframe\n */\n public setIframeDisplayMode(mode: \"modal\" | \"embedded\"): void {\n this.config.iframeDisplayMode = mode;\n this.logger.debug(`Iframe display mode updated to: ${mode}`);\n }\n\n /**\n * Get the current iframe display mode\n * @returns The current iframe display mode\n */\n public getIframeDisplayMode(): \"modal\" | \"embedded\" | undefined {\n return this.config.iframeDisplayMode;\n }\n\n /**\n * Destroy the auth client and clean up all resources\n */\n public async destroy(): Promise<void> {\n this.cleanup();\n await this.sessionManager.destroy();\n this.logger.info(\"CivicAuth destroyed\");\n }\n\n /**\n * Handle logout\n */\n public async logout(): Promise<void> {\n try {\n this.logger.info(\"๐ Starting logout process\");\n this.events.emit(AuthEvent.SIGN_OUT_STARTED, {\n detail: \"Logout process started\",\n });\n\n // Get current tokens before clearing them\n const tokens = await retrieveTokens(this.storage);\n\n if (!tokens?.id_token) {\n this.logger.warn(\"โ ๏ธ No ID token found, clearing local session only\");\n await clearTokens(this.storage);\n await this.sessionManager.clearSession();\n this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {\n detail: \"Local session cleared\",\n });\n return;\n }\n\n if (!this.endpoints) {\n throw new Error(\"OAuth endpoints not initialized\");\n }\n\n // Generate a state for logout\n const state = generateState({\n displayMode: this.config.displayMode || \"iframe\",\n });\n\n // Generate logout URL\n const logoutUrl = await generateOauthLogoutUrl({\n clientId: this.config.clientId,\n redirectUrl: this.config.redirectUrl,\n idToken: tokens.id_token,\n state: state,\n oauthServer: this.config.oauthServerBaseUrl,\n });\n\n this.logger.info(\"๐ Generated logout URL\", {\n logoutUrl: logoutUrl.toString(),\n });\n\n // Clear local tokens and session\n await clearTokens(this.storage);\n await this.sessionManager.clearSession();\n\n // Emit logout complete event before redirect\n this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {\n detail: \"Logout successful\",\n });\n\n // Redirect to logout URL\n this.logger.info(\"๐ Redirecting to logout URL\");\n window.location.href = logoutUrl.toString();\n } catch (error) {\n this.logger.error(\"โ Logout failed\", { error });\n this.events.emit(AuthEvent.SIGN_OUT_ERROR, {\n detail: error instanceof Error ? error.message : String(error),\n });\n throw new CivicAuthError(\n \"Logout failed\",\n CivicAuthErrorCode.LOGOUT_FAILED,\n );\n }\n }\n}\n\n// Export types for external use\nexport type { CivicAuthClientConfig } from \"./types/AuthTypes.js\";\nexport { CivicAuthErrorCode } from \"./types/AuthTypes.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"CivicAuth.js","sourceRoot":"","sources":["../../../src/vanillajs/auth/CivicAuth.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../types/index.js\";\nimport type { Endpoints, AuthStorage } from \"../../types.js\";\nimport { buildAuthUrl, extractTokensFromSession } from \"../utils/auth-utils.js\";\nimport type { AuthResult, Session } from \"../types/index.js\";\nimport type { createLogger } from \"../utils/logger.js\";\nimport {\n createMainLogger,\n configureLogging,\n setCurrentLogger,\n} from \"../utils/logger.js\";\nimport { GenericPublicClientPKCEProducer } from \"../../services/PKCE.js\";\nimport { generateState } from \"../../lib/oauth.js\";\nimport { SessionManager } from \"./SessionManager.js\";\nimport { AuthenticationEvents } from \"./AuthenticationEvents.js\";\nimport { PopupError } from \"../../services/types.js\";\nimport { handleOAuthRedirectPage } from \"./handlers/OAuthCallbackHandler.js\";\nimport {\n generateOauthLogoutUrl,\n clearTokens,\n retrieveTokens,\n} from \"../../shared/lib/util.js\";\nimport { LOGOUT_STATE } from \"../../constants.js\";\nimport { getOauthEndpoints } from \"../../lib/oauth.js\";\n\n// Import new modular components\nimport type {\n CivicAuthClientConfig,\n ProcessedCivicAuthConfig,\n} from \"./types/AuthTypes.js\";\nimport {\n CivicAuthError,\n CivicAuthErrorCode,\n CIVIC_AUTH_CONSTANTS,\n} from \"./types/AuthTypes.js\";\nimport { processConfigWithDefaults } from \"./config/ConfigProcessor.js\";\nimport { MessageHandler } from \"./handlers/MessageHandler.js\";\nimport { PopupHandler } from \"./handlers/PopupHandler.js\";\nimport { IframeAuthHandler } from \"./handlers/IframeAuthHandler.js\";\n\n/**\n * CivicAuth client for handling OAuth authentication\n *\n * This is a refactored version that uses a modular architecture for better maintainability.\n */\nexport class CivicAuth {\n private config: ProcessedCivicAuthConfig;\n private storage: AuthStorage;\n private endpoints?: Endpoints;\n private logger: ReturnType<typeof createLogger>;\n private sessionManager: SessionManager;\n private events: AuthenticationEvents;\n private initialDisplayMode:\n | \"iframe\"\n | \"modal\"\n | \"redirect\"\n | \"new_tab\"\n | \"custom_tab\";\n\n // Authentication state\n private authPromise?: Promise<AuthResult>;\n private authPromiseResolve?: (value: AuthResult) => void;\n private authPromiseReject?: (reason?: Error) => void;\n private authProcessTimeoutHandle?: number;\n private popupFailureTimeoutHandle?: number;\n private hasPopupFailed: boolean = false;\n\n // Handlers\n private messageHandler?: MessageHandler;\n private popupHandler?: PopupHandler;\n private iframeAuthHandler?: IframeAuthHandler;\n\n /**\n * Private constructor - initializes configuration and handlers.\n * Use {@link CivicAuth.create} to create a new instance.\n */\n private constructor(config: CivicAuthClientConfig) {\n // Process config with defaults and validation\n this.config = processConfigWithDefaults(config);\n this.initialDisplayMode = this.config.displayMode;\n\n // Configure logging\n configureLogging(this.config.logging);\n\n // Initialize logger - always use \"vanillajs\" as base namespace\n if (this.config.logging?.enabled) {\n this.logger = createMainLogger(\"vanillajs\"); // Always use \"vanillajs\"\n } else {\n this.logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n setCurrentLogger(this.logger);\n this.storage = this.config.storageAdapter;\n\n // Always initialize events - use provided events or create default instance\n this.events = config.events || new AuthenticationEvents();\n\n // Always initialize SessionManager\n this.sessionManager = new SessionManager(this.storage, this.events);\n\n // Initialize handlers\n this.initializeHandlers();\n }\n\n /**\n * Creates and initializes a new instance of CivicAuth.\n * This is the recommended way to create a CivicAuth instance.\n *\n * @param config - Configuration options for the auth client\n * @returns A promise that resolves with the initialized CivicAuth instance\n * @throws {CivicAuthError} If initialization fails or required configuration is missing\n *\n * @example\n * ```typescript\n * const auth = await CivicAuth.create({\n * clientId: \"your-client-id\",\n * // redirectUrl is optional - defaults to current page (window.location.origin + window.location.pathname)\n * redirectUrl: \"https://your-app.com/callback\", // optional\n * // logoutRedirectUrl is optional - defaults to redirectUrl if not provided\n * logoutRedirectUrl: \"https://your-app.com/logout\", // optional\n * // oauthServerBaseUrl is optional - defaults to \"https://auth.civic.com/oauth\"\n * oauthServerBaseUrl: \"https://auth-server.com/\", // optional\n * // scopes is optional - defaults to ['openid', 'profile', 'email', 'offline_access']\n * scopes: [\"openid\", \"profile\"], // optional\n * targetContainerElement: \"auth-container\",\n * textSignals: {\n * success: \"Authentication successful!\"\n * }\n * });\n * ```\n */\n public static async create(\n config: CivicAuthClientConfig,\n ): Promise<CivicAuth> {\n const instance = new CivicAuth(config);\n await instance.init();\n return instance;\n }\n\n /**\n * Initializes the auth client and checks for callback handling\n */\n private async init(): Promise<void> {\n this.logger.info(\"๐ Initializing CivicAuth\", {\n currentUrl: window.location.href,\n redirectUrl: this.config.redirectUrl,\n oauthServerBaseUrl: this.config.oauthServerBaseUrl,\n isCallbackUrl: window.location.href.startsWith(this.config.redirectUrl),\n });\n\n try {\n // Get OAuth endpoints using shared function (handles trailing slash automatically)\n this.endpoints = await getOauthEndpoints(this.config.oauthServerBaseUrl);\n\n this.logger.info(\"๐ OAuth endpoints configured\", {\n endpoints: this.endpoints,\n });\n\n // Initialize SessionManager with auth config\n if (this.sessionManager) {\n const authConfig = {\n clientId: this.config.clientId,\n redirectUrl: this.config.redirectUrl,\n oauthServer: this.config.oauthServerBaseUrl,\n scopes: this.config.scopes,\n endpoints: this.endpoints,\n };\n this.logger.info(\"๐ง Initializing SessionManager\", { authConfig });\n await this.sessionManager.initializeWithAuthConfig(authConfig);\n }\n\n // Check if we're on the callback page\n const isCallbackPage = window.location.href.startsWith(\n this.config.redirectUrl,\n );\n this.logger.info(\"๐ Callback page check\", {\n isCallbackPage,\n currentUrl: window.location.href,\n redirectUrl: this.config.redirectUrl,\n });\n\n // Handle logout state cleanup first (before processing auth callbacks)\n await this.handleLogoutStateCleanup();\n\n if (isCallbackPage) {\n this.logger.info(\"๐ Processing callback page\");\n await this.handleCallback();\n } else {\n this.logger.info(\"๐ Not a callback page, initialization complete\");\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? error.message\n : \"Failed to initialize authentication\";\n this.logger.error(\"โ CivicAuth initialization failed\", {\n error: errorMessage,\n stack: error instanceof Error ? error.stack : undefined,\n });\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: errorMessage,\n });\n throw new CivicAuthError(errorMessage, CivicAuthErrorCode.INIT_FAILED);\n }\n }\n\n /**\n * Initialize all handlers with proper configuration\n */\n private initializeHandlers(): void {\n const handlerConfig = {\n config: this.config,\n logger: this.logger,\n onAuthSuccess: this.handleAuthSuccess.bind(this),\n onAuthError: this.handleAuthError.bind(this),\n cleanup: this.cleanup.bind(this),\n };\n\n this.messageHandler = new MessageHandler({\n ...handlerConfig,\n onPopupFailure: this.handlePopupFailure.bind(this),\n });\n\n this.popupHandler = new PopupHandler(handlerConfig);\n\n this.iframeAuthHandler = new IframeAuthHandler({\n ...handlerConfig,\n messageHandler: this.messageHandler.handleMessage,\n });\n }\n\n /**\n * Builds the authentication URL with PKCE challenge\n */\n private async buildAuthUrl(): Promise<string> {\n if (!this.endpoints) {\n throw new CivicAuthError(\n \"OAuth endpoints not initialized. Please wait for initialization to complete.\",\n CivicAuthErrorCode.ENDPOINTS_NOT_INITIALIZED,\n );\n }\n\n const pkceProducer = new GenericPublicClientPKCEProducer(this.storage);\n const codeChallenge = await pkceProducer.getCodeChallenge();\n const state =\n this.config.initialState ||\n generateState({\n displayMode: this.config.displayMode || \"iframe\",\n });\n\n return buildAuthUrl({\n endpoints: this.endpoints,\n clientId: this.config.clientId,\n redirectUrl: this.config.redirectUrl,\n scopes: this.config.scopes,\n codeChallenge,\n state,\n prompt: this.config.prompt,\n nonce: this.config.nonce,\n });\n }\n\n /**\n * Starts the authentication process\n * @returns A promise that resolves with the authentication result\n * @throws {CivicAuthError} If authentication fails or times out\n */\n async startAuthentication(): Promise<AuthResult> {\n this.logger.info(\"๐ฌ Starting authentication process\", {\n displayMode: this.config.displayMode,\n userAgent: navigator.userAgent,\n currentUrl: window.location.href,\n });\n\n if (!this.endpoints) {\n const error = new CivicAuthError(\n \"OAuth endpoints not initialized. Please wait for initialization to complete.\",\n CivicAuthErrorCode.ENDPOINTS_NOT_INITIALIZED,\n );\n this.logger.error(\"โ Endpoints not initialized\", {\n error: error.message,\n });\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: error.message,\n });\n throw error;\n }\n\n if (this.authPromise) {\n this.logger.info(\n \"โณ Authentication already in progress, returning existing promise\",\n );\n return this.authPromise;\n }\n\n const fullAuthUrl = await this.buildAuthUrl();\n this.logger.info(\"๐ Built authentication URL\", {\n url: fullAuthUrl,\n displayMode: this.config.displayMode,\n authProcessTimeout: this.config.authProcessTimeout,\n });\n\n this.authPromise = new Promise<AuthResult>((resolve, reject) => {\n this.authPromiseResolve = resolve;\n this.authPromiseReject = reject;\n\n this.handleAuthenticationByDisplayMode(fullAuthUrl);\n this.setupAuthenticationTimeout();\n });\n\n return this.authPromise;\n }\n\n /**\n * Handle authentication based on display mode\n */\n private async handleAuthenticationByDisplayMode(\n fullAuthUrl: string,\n ): Promise<void> {\n this.logger.info(\"๐ฏ Handling authentication with display mode\", {\n displayMode: this.config.displayMode,\n });\n\n try {\n switch (this.config.displayMode) {\n case \"redirect\":\n this.logger.info(\"๐ Using redirect mode\");\n window.location.href = fullAuthUrl;\n break;\n\n case \"new_tab\":\n this.logger.info(\"๐ฑ Using new_tab mode\");\n if (!this.popupHandler) {\n throw new Error(\"Popup handler not initialized\");\n }\n await this.popupHandler.handleNewTabAuth(fullAuthUrl);\n break;\n\n case \"iframe\":\n default: {\n this.logger.info(\"๐ผ๏ธ Using iframe mode\");\n if (!this.iframeAuthHandler || !this.messageHandler) {\n throw new Error(\"Iframe handler not initialized\");\n }\n const iframeElement =\n await this.iframeAuthHandler.handleIframeAuth(fullAuthUrl);\n this.messageHandler.updateIframeElement(iframeElement);\n break;\n }\n }\n } catch (error) {\n if (error instanceof PopupError) {\n await this.handlePopupErrorWithFallback(fullAuthUrl, error);\n } else {\n this.handleAuthError(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n\n /**\n * Handle popup error with redirect fallback\n */\n private async handlePopupErrorWithFallback(\n fullAuthUrl: string,\n error: PopupError,\n ): Promise<void> {\n this.logger.warn(\"๐ซ Popup failed, falling back to redirect mode\", {\n originalDisplayMode: this.config.displayMode,\n error: error.message,\n });\n\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Popup blocked, falling back to redirect mode\",\n });\n\n try {\n this.logger.info(\"๐ Attempting redirect fallback\");\n\n // Clean up current authentication attempt\n this.cleanup();\n\n // Always switch to redirect mode for Safari compatibility\n this.config.displayMode = \"redirect\";\n\n // Regenerate the auth URL with updated display mode in state\n const fallbackAuthUrl = await this.buildAuthUrl();\n\n this.logger.info(\"๐ Redirecting to auth URL\", { url: fallbackAuthUrl });\n window.location.href = fallbackAuthUrl;\n this.logger.info(\"โ
Redirect initiated successfully\");\n } catch (redirectError) {\n this.logger.error(\"โ Redirect fallback failed\", {\n error: redirectError,\n redirectUrl: fullAuthUrl,\n });\n\n const fallbackError = new CivicAuthError(\n \"Failed to open popup window and redirect fallback failed. Please check your browser's popup settings.\",\n CivicAuthErrorCode.INIT_FAILED,\n );\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: fallbackError.message,\n });\n this.handleAuthError(fallbackError);\n }\n }\n\n /**\n * Setup authentication timeout\n */\n private setupAuthenticationTimeout(): void {\n // Skip timeout for embedded iframe mode - embedded iframes should stay persistent\n if (\n this.config.displayMode === \"iframe\" &&\n this.config.iframeDisplayMode === \"embedded\"\n ) {\n this.logger.debug(\n \"โฐ Skipping authentication timeout for embedded iframe mode\",\n {\n displayMode: this.config.displayMode,\n iframeDisplayMode: this.config.iframeDisplayMode,\n },\n );\n return;\n }\n\n if (this.config.authProcessTimeout && this.config.authProcessTimeout > 0) {\n this.logger.debug(\"โฐ Setting up authentication timeout\", {\n authProcessTimeout: this.config.authProcessTimeout,\n displayMode: this.config.displayMode,\n iframeDisplayMode: this.config.iframeDisplayMode,\n });\n\n this.authProcessTimeoutHandle = window.setTimeout(() => {\n this.logger.error(\"โฐ Authentication timed out\", {\n displayMode: this.config.displayMode,\n iframeDisplayMode: this.config.iframeDisplayMode,\n currentOrigin: window.location.origin,\n authProcessTimeout: this.config.authProcessTimeout,\n });\n\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication timed out\",\n });\n\n const error = new CivicAuthError(\n \"Authentication timed out\",\n CivicAuthErrorCode.AUTH_PROCESS_TIMEOUT,\n );\n this.handleAuthError(error);\n }, this.config.authProcessTimeout);\n }\n }\n\n /**\n * Handle successful authentication\n */\n private handleAuthSuccess(result: AuthResult): void {\n this.logger.info(\"โ
Authentication successful\");\n this.authPromiseResolve?.(result);\n this.cleanup();\n }\n\n /**\n * Handle authentication error\n */\n private handleAuthError(error: Error): void {\n this.logger.error(\"โ Authentication failed\", { error: error.message });\n this.authPromiseReject?.(error);\n this.cleanup();\n }\n\n /**\n * Handle popup failure - simplified like React implementation\n */\n private handlePopupFailure(failedUrl?: string): void {\n this.hasPopupFailed = true;\n\n this.logger.warn(\"Popup failed, using redirect mode instead...\", {\n failedUrl,\n });\n\n // Clean up iframe if it exists\n if (this.iframeAuthHandler) {\n this.iframeAuthHandler.cleanupIframe();\n }\n\n // Always redirect to the failed URL or build a new one\n if (failedUrl) {\n window.location.href = failedUrl;\n } else {\n this.buildAuthUrl()\n .then((authUrl) => {\n window.location.href = authUrl;\n })\n .catch((error) => {\n this.logger.error(\"Failed to build auth URL for redirect fallback\", {\n error,\n });\n const fallbackError = new CivicAuthError(\n \"Failed to redirect for authentication\",\n CivicAuthErrorCode.INIT_FAILED,\n );\n this.handleAuthError(fallbackError);\n });\n }\n }\n\n /**\n * Show popup failure message to user\n */\n private showPopupFailureMessage(\n customMessage: string = \"Authentication will continue in this window. Please wait...\",\n ): void {\n const container = this.getContainerElement();\n if (!container) {\n this.logger.warn(\n \"Cannot show popup failure message - container not found\",\n );\n return;\n }\n const existingMessage = document.getElementById(\n \"civic-auth-popup-failure-message\",\n );\n if (existingMessage && existingMessage.parentNode) {\n existingMessage.parentNode.removeChild(existingMessage);\n }\n const messageOverlay = document.createElement(\"div\");\n messageOverlay.id = \"civic-auth-popup-failure-message\";\n messageOverlay.style.cssText =\n \"position:absolute;top:0;left:0;right:0;background:rgba(255,249,196,.95);border:1px solid #f59e0b;border-radius:6px;padding:12px;margin:8px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;color:#92400e;z-index:1000;box-shadow:0 2px 4px rgba(0,0,0,.1);\";\n messageOverlay.innerHTML =\n '<div style=\"display:flex;align-items:center;gap:8px;\">' +\n '<span style=\"font-size:16px;\">โ ๏ธ</span>' +\n \"<div>\" +\n \"<strong>Popup blocked</strong><br>\" +\n '<span style=\"font-size:12px;\">' +\n customMessage +\n \"</span>\" +\n \"</div>\" +\n \"</div>\";\n\n if (getComputedStyle(container).position === \"static\") {\n container.style.position = \"relative\";\n }\n\n container.appendChild(messageOverlay);\n\n setTimeout(() => {\n if (messageOverlay.parentNode) {\n messageOverlay.parentNode.removeChild(messageOverlay);\n }\n }, 10000);\n this.logger.info(\"Popup failure message displayed to user\");\n }\n\n /**\n * Setup popup failure timeout\n */\n private setupPopupFailureTimeout(): void {\n this.popupFailureTimeoutHandle = window.setTimeout(() => {\n this.logger.info(\"โฐ Popup failure timeout reached\");\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication timeout - popup failure scenario\",\n });\n\n const error = new CivicAuthError(\n \"Authentication timeout - popup failure scenario\",\n CivicAuthErrorCode.AUTH_PROCESS_TIMEOUT,\n );\n this.handleAuthError(error);\n }, 20000); // 20 seconds\n }\n\n /**\n * Gets the container element for the auth iframe\n */\n private getContainerElement(): HTMLElement | null {\n if (typeof this.config.targetContainerElement === \"string\") {\n const element = document.getElementById(\n this.config.targetContainerElement,\n );\n if (!element) {\n this.logger.warn(\n `Container element with ID \"${this.config.targetContainerElement}\" not found`,\n );\n }\n return element;\n }\n return this.config.targetContainerElement ?? null;\n }\n\n /**\n * Handle OAuth callback\n */\n private async handleCallback(): Promise<void> {\n this.logger.info(\"๐ Handling OAuth callback\", {\n currentUrl: window.location.href,\n redirectUrl: this.config.redirectUrl,\n });\n\n try {\n const callbackHandled = await handleOAuthRedirectPage({\n clientId: this.config.clientId,\n oauthServer: this.config.oauthServerBaseUrl,\n redirectUrl: this.config.redirectUrl,\n textSignals: {\n success: this.config.textSignals.success,\n error: this.config.textSignals.error || \"Authentication failed\",\n },\n storageAdapter: this.storage,\n });\n\n this.logger.info(\"๐ Callback processing result\", { callbackHandled });\n\n if (callbackHandled) {\n const successSignal = document.getElementById(\n CIVIC_AUTH_CONSTANTS.SUCCESS_SIGNAL_ID,\n );\n const errorSignal = document.getElementById(\n CIVIC_AUTH_CONSTANTS.ERROR_SIGNAL_ID,\n );\n\n if (successSignal) {\n this.logger.info(\"โ
Success signal found\");\n let userInfo = null;\n const userInfoAttr = successSignal.getAttribute(\"data-user-info\");\n if (userInfoAttr) {\n try {\n userInfo = JSON.parse(userInfoAttr);\n } catch (error) {\n this.logger.error(\"โ Failed to parse user info\", { error });\n }\n }\n this.events.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Callback processed successfully\",\n user: userInfo,\n });\n } else if (errorSignal) {\n this.logger.error(\"โ Error signal found\");\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: errorSignal.textContent || \"Unknown error during callback\",\n });\n }\n }\n } catch (error) {\n this.logger.error(\"โ Callback handling failed\", { error });\n this.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail:\n error instanceof Error\n ? error.message\n : \"Unknown error during callback\",\n });\n }\n }\n\n /**\n * Cleans up resources and event listeners\n */\n public cleanup(): void {\n this.logger.info(\"Cleaning up authentication client\");\n\n // Clean up handlers\n this.iframeAuthHandler?.cleanupIframe();\n\n // Clean up timeouts\n if (this.authProcessTimeoutHandle) {\n window.clearTimeout(this.authProcessTimeoutHandle);\n this.authProcessTimeoutHandle = undefined;\n }\n\n if (this.popupFailureTimeoutHandle) {\n window.clearTimeout(this.popupFailureTimeoutHandle);\n this.popupFailureTimeoutHandle = undefined;\n }\n\n // Reset state\n this.hasPopupFailed = false;\n this.authPromise = undefined;\n this.authPromiseResolve = undefined;\n this.authPromiseReject = undefined;\n\n // Remove message event listener\n if (this.messageHandler) {\n window.removeEventListener(\"message\", this.messageHandler.handleMessage);\n }\n }\n\n /**\n * Get the current session\n */\n public async getCurrentSession(): Promise<Session | null> {\n return this.sessionManager.getCurrentSession() || null;\n }\n\n /**\n * Get current session tokens including decoded forwarded tokens\n * This method extracts and decodes forwarded tokens from the ID token JWT\n */\n public async getTokensWithForwardedTokens() {\n const session = await this.getCurrentSession();\n return extractTokensFromSession(session);\n }\n\n /**\n * Check if user is authenticated\n */\n public async isAuthenticated(): Promise<boolean> {\n return this.sessionManager.isAuthenticated() || false;\n }\n\n /**\n * Get the current user\n */\n public async getCurrentUser() {\n return this.sessionManager.getCurrentUser() || null;\n }\n\n /**\n * Clear the current session\n */\n public async clearSession(): Promise<void> {\n return this.sessionManager.clearSession();\n }\n\n /**\n * Manually refresh tokens\n */\n public async refreshTokens(): Promise<void> {\n return this.sessionManager.refreshTokens();\n }\n\n /**\n * Get token refresher state for debugging\n */\n public getTokenRefresherState() {\n return this.sessionManager.getTokenRefresherState() || null;\n }\n\n /**\n * Update the iframe display mode\n * @param mode - The display mode to use for the iframe\n */\n public setIframeDisplayMode(mode: \"modal\" | \"embedded\"): void {\n this.config.iframeDisplayMode = mode;\n this.logger.debug(`Iframe display mode updated to: ${mode}`);\n }\n\n /**\n * Get the current iframe display mode\n * @returns The current iframe display mode\n */\n public getIframeDisplayMode(): \"modal\" | \"embedded\" | undefined {\n return this.config.iframeDisplayMode;\n }\n\n /**\n * Destroy the auth client and clean up all resources\n */\n public async destroy(): Promise<void> {\n this.cleanup();\n await this.sessionManager.destroy();\n this.logger.info(\"CivicAuth destroyed\");\n }\n\n /**\n * Handle logout\n */\n public async logout(): Promise<void> {\n try {\n this.logger.info(\"๐ Starting logout process\");\n this.events.emit(AuthEvent.SIGN_OUT_STARTED, {\n detail: \"Logout process started\",\n });\n\n // Get current tokens before clearing them\n const tokens = await retrieveTokens(this.storage);\n\n if (!tokens?.id_token) {\n this.logger.warn(\"โ ๏ธ No ID token found, clearing local session only\");\n await clearTokens(this.storage);\n await this.sessionManager.clearSession();\n this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {\n detail: \"Local session cleared\",\n });\n return;\n }\n\n if (!this.endpoints) {\n throw new Error(\"OAuth endpoints not initialized\");\n }\n\n // Generate a state for logout\n const state = generateState({\n displayMode: this.config.displayMode || \"iframe\",\n });\n\n this.logger.info(\"๐ Storing logout state\", {\n generatedState: state,\n logoutStateKey: LOGOUT_STATE,\n displayMode: this.config.displayMode,\n });\n\n // Store logout state for cleanup after redirect\n // This matches the React implementation - only store state for redirect flow\n await this.storage.set(LOGOUT_STATE, state);\n\n // Generate logout URL\n const logoutUrl = await generateOauthLogoutUrl({\n clientId: this.config.clientId,\n redirectUrl: this.config.logoutRedirectUrl,\n idToken: tokens.id_token,\n state: state,\n oauthServer: this.config.oauthServerBaseUrl,\n });\n\n this.logger.info(\"๐ Generated logout URL\", {\n logoutUrl: logoutUrl.toString(),\n });\n\n // Clear local tokens and session but NOT the logout state (needed for cleanup after redirect)\n await this.sessionManager.clearSession(true); // preserveLogoutState = true\n\n // Emit logout complete event before redirect\n this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {\n detail: \"Logout successful\",\n });\n\n // Redirect to logout URL\n this.logger.info(\"๐ Redirecting to logout URL\");\n window.location.href = logoutUrl.toString();\n } catch (error) {\n this.logger.error(\"โ Logout failed\", { error });\n this.events.emit(AuthEvent.SIGN_OUT_ERROR, {\n detail: error instanceof Error ? error.message : String(error),\n });\n throw new CivicAuthError(\n \"Logout failed\",\n CivicAuthErrorCode.LOGOUT_FAILED,\n );\n }\n }\n\n /**\n * Handle logout state cleanup\n * This mirrors the logic from useSignIn.ts to properly clean up after logout\n */\n private async handleLogoutStateCleanup(): Promise<void> {\n try {\n const params = new URLSearchParams(window.location.search);\n const state = params.get(\"state\");\n\n this.logger.info(\"๐ Checking for logout state cleanup\", {\n currentUrl: window.location.href,\n hasStateParam: !!state,\n stateValue: state,\n rawSearch: window.location.search,\n });\n\n if (!state) {\n this.logger.info(\n \"๐ No state parameter found, skipping logout cleanup\",\n );\n return; // No state parameter, nothing to cleanup\n }\n\n // Check if we have a stored logout state that matches\n const storedLogoutState = await this.storage.get(LOGOUT_STATE);\n\n // The state might be URL-decoded by URLSearchParams, but stored as plain\n // Let's try both the decoded and encoded versions\n const decodedState = decodeURIComponent(state);\n\n this.logger.info(\"๐ Comparing logout states\", {\n urlState: state,\n decodedState,\n storedLogoutState,\n directMatch: state === storedLogoutState,\n decodedMatch: decodedState === storedLogoutState,\n });\n\n if (state === storedLogoutState || decodedState === storedLogoutState) {\n this.logger.info(\"๐งน Cleaning up logout state\", {\n state,\n storedLogoutState,\n });\n\n // Clear tokens and user data from storage\n await clearTokens(this.storage);\n await this.sessionManager.clearSession();\n\n // Clean up the logout state from storage\n await this.storage.delete(LOGOUT_STATE);\n\n // Emit logout complete event\n this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {\n detail: \"Logout cleanup completed\",\n });\n\n // Clean up URL by removing query parameters\n const cleanUrl = window.location.href.split(\"?\")[0];\n window.history.replaceState({}, document.title, cleanUrl);\n\n this.logger.info(\"โ
Logout state cleanup completed\", {\n cleanUrl,\n });\n } else {\n this.logger.info(\"๐ Logout states don't match, skipping cleanup\", {\n urlState: state,\n storedLogoutState,\n });\n }\n } catch (error) {\n this.logger.warn(\"โ ๏ธ Error during logout state cleanup\", { error });\n // Don't throw error to prevent initialization failure\n }\n }\n}\n\n// Export types for external use\nexport type { CivicAuthClientConfig } from \"./types/AuthTypes.js\";\nexport { CivicAuthErrorCode } from \"./types/AuthTypes.js\";\n"]}
|