@civic/auth 0.11.0-beta.0 → 0.11.0-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 +1 -0
- package/dist/browser/storage.d.ts +1 -0
- package/dist/browser/storage.d.ts.map +1 -1
- package/dist/browser/storage.js +1 -0
- package/dist/browser/storage.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/nextjs/hooks/useInitialAuthConfig.d.ts +3 -1
- package/dist/nextjs/hooks/useInitialAuthConfig.d.ts.map +1 -1
- package/dist/nextjs/hooks/useInitialAuthConfig.js +5 -6
- package/dist/nextjs/hooks/useInitialAuthConfig.js.map +1 -1
- package/dist/nextjs/providers/NextAuthProviderClient.d.ts.map +1 -1
- package/dist/nextjs/providers/NextAuthProviderClient.js +9 -3
- package/dist/nextjs/providers/NextAuthProviderClient.js.map +1 -1
- package/dist/react-router-7/components/UserButton.d.ts +3 -3
- package/dist/react-router-7/components/UserButton.d.ts.map +1 -1
- package/dist/react-router-7/components/UserButton.js +3 -2
- package/dist/react-router-7/components/UserButton.js.map +1 -1
- package/dist/react-router-7/cookies.d.ts +4 -0
- package/dist/react-router-7/cookies.d.ts.map +1 -1
- package/dist/react-router-7/cookies.js +22 -0
- package/dist/react-router-7/cookies.js.map +1 -1
- package/dist/react-router-7/useUser.d.ts.map +1 -1
- package/dist/react-router-7/useUser.js +5 -2
- package/dist/react-router-7/useUser.js.map +1 -1
- package/dist/reactjs/components/UserButton.d.ts +3 -3
- package/dist/reactjs/components/UserButton.d.ts.map +1 -1
- package/dist/reactjs/components/UserButton.js +9 -3
- package/dist/reactjs/components/UserButton.js.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.d.ts +13 -3
- package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.js +40 -7
- package/dist/reactjs/core/GlobalAuthManager.js.map +1 -1
- package/dist/reactjs/hooks/useToken.d.ts +2 -2
- package/dist/reactjs/hooks/useToken.d.ts.map +1 -1
- package/dist/reactjs/hooks/useToken.js.map +1 -1
- package/dist/reactjs/hooks/useUser.d.ts +10 -4
- package/dist/reactjs/hooks/useUser.d.ts.map +1 -1
- package/dist/reactjs/hooks/useUser.js +13 -8
- package/dist/reactjs/hooks/useUser.js.map +1 -1
- package/dist/reactjs/index.d.ts +0 -2
- package/dist/reactjs/index.d.ts.map +1 -1
- package/dist/reactjs/index.js +0 -2
- package/dist/reactjs/index.js.map +1 -1
- package/dist/reactjs/providers/CivicAuthProvider.d.ts +10 -3
- package/dist/reactjs/providers/CivicAuthProvider.d.ts.map +1 -1
- package/dist/reactjs/providers/CivicAuthProvider.js.map +1 -1
- package/dist/reactjs/providers/index.d.ts +0 -1
- package/dist/reactjs/providers/index.d.ts.map +1 -1
- package/dist/reactjs/providers/index.js +0 -1
- package/dist/reactjs/providers/index.js.map +1 -1
- package/dist/shared/lib/storage.d.ts +1 -0
- package/dist/shared/lib/storage.d.ts.map +1 -1
- package/dist/shared/lib/storage.js +1 -0
- package/dist/shared/lib/storage.js.map +1 -1
- package/dist/shared/providers/types.d.ts +4 -2
- package/dist/shared/providers/types.d.ts.map +1 -1
- package/dist/shared/providers/types.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 +24 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vanillajs/auth/SessionManager.js +1 -1
- package/dist/vanillajs/auth/SessionManager.js.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.js +5 -3
- package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
- package/dist/vanillajs/index.d.ts +1 -1
- package/dist/vanillajs/index.d.ts.map +1 -1
- package/dist/vanillajs/index.js.map +1 -1
- package/dist/vanillajs/types/index.d.ts +8 -0
- package/dist/vanillajs/types/index.d.ts.map +1 -1
- package/dist/vanillajs/types/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/reactjs/providers/CivicAuthContext.d.ts +0 -44
- package/dist/reactjs/providers/CivicAuthContext.d.ts.map +0 -1
- package/dist/reactjs/providers/CivicAuthContext.js +0 -313
- package/dist/reactjs/providers/CivicAuthContext.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AuthStorage } from "../types.js";
|
|
2
2
|
import { EventEmitter } from "eventemitter3";
|
|
3
3
|
export declare class LocalStorageAdapter implements AuthStorage {
|
|
4
|
+
storageType: "localStorage";
|
|
4
5
|
static _emitter: EventEmitter;
|
|
5
6
|
static get emitter(): EventEmitter;
|
|
6
7
|
getSync(key: string): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/browser/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,qBAAa,mBAAoB,YAAW,WAAW;IACrD,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC;IAC9B,MAAM,KAAK,OAAO,IAAI,YAAY,CAKjC;IAED,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI7B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzC"}
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/browser/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,qBAAa,mBAAoB,YAAW,WAAW;IACrD,WAAW,EAAG,cAAc,CAAU;IACtC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC;IAC9B,MAAM,KAAK,OAAO,IAAI,YAAY,CAKjC;IAED,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI7B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzC"}
|
package/dist/browser/storage.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/browser/storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,OAAO,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAe;IAC9B,MAAM,KAAK,OAAO;QAChB,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC;YAClC,mBAAmB,CAAC,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;QACpD,CAAC;QACD,OAAO,mBAAmB,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,OAAO,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAClC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;CACF","sourcesContent":["import type { AuthStorage } from \"@/types.js\";\nimport { EventEmitter } from \"eventemitter3\";\n\nexport class LocalStorageAdapter implements AuthStorage {\n static _emitter: EventEmitter;\n static get emitter(): EventEmitter {\n if (!LocalStorageAdapter._emitter) {\n LocalStorageAdapter._emitter = new EventEmitter();\n }\n return LocalStorageAdapter._emitter;\n }\n\n getSync(key: string): string | null {\n return localStorage.getItem(key);\n }\n\n async get(key: string): Promise<string> {\n return Promise.resolve(localStorage.getItem(key) || \"\");\n }\n\n async set(key: string, value: string): Promise<void> {\n localStorage.setItem(key, value);\n }\n\n async delete(key: string): Promise<void> {\n localStorage.removeItem(key);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/browser/storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,OAAO,mBAAmB;IAC9B,WAAW,GAAG,cAAuB,CAAC;IACtC,MAAM,CAAC,QAAQ,CAAe;IAC9B,MAAM,KAAK,OAAO;QAChB,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC;YAClC,mBAAmB,CAAC,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;QACpD,CAAC;QACD,OAAO,mBAAmB,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,OAAO,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAClC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;CACF","sourcesContent":["import type { AuthStorage } from \"@/types.js\";\nimport { EventEmitter } from \"eventemitter3\";\n\nexport class LocalStorageAdapter implements AuthStorage {\n storageType = \"localStorage\" as const;\n static _emitter: EventEmitter;\n static get emitter(): EventEmitter {\n if (!LocalStorageAdapter._emitter) {\n LocalStorageAdapter._emitter = new EventEmitter();\n }\n return LocalStorageAdapter._emitter;\n }\n\n getSync(key: string): string | null {\n return localStorage.getItem(key);\n }\n\n async get(key: string): Promise<string> {\n return Promise.resolve(localStorage.getItem(key) || \"\");\n }\n\n async set(key: string, value: string): Promise<void> {\n localStorage.setItem(key, value);\n }\n\n async delete(key: string): Promise<void> {\n localStorage.removeItem(key);\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Tokens, Endpoints, Config, User, DisplayMode, ForwardedTokens, AuthStorage, } from "./types.js";
|
|
1
|
+
export type { Tokens, Endpoints, Config, User, DisplayMode, ForwardedTokens, AuthStorage, AuthStatusEnum, CivicAuthContextType, } from "./types.js";
|
|
2
2
|
export { AuthStatus } from "./types.js";
|
|
3
3
|
export type * from "./shared/lib/types.js";
|
|
4
4
|
export type { UserContextType } from "./shared/providers/UserProvider.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,MAAM,EACN,SAAS,EACT,MAAM,EACN,IAAI,EACJ,WAAW,EACX,eAAe,EACf,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,MAAM,EACN,SAAS,EACT,MAAM,EACN,IAAI,EACJ,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,mBAAmB,uBAAuB,CAAC;AAE3C,YAAY,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAgB,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,CAAC;AACf,OAAO,EAAE,OAAO,EAAE,CAAC","sourcesContent":["// These are the default exports of the project.\n// They are limited by design to ensure that the public API does not expose any internal implementation details.\n// Do not change this without thinking carefully about the impact on the client-facing public API.\nexport type {\n Tokens,\n Endpoints,\n Config,\n User,\n DisplayMode,\n ForwardedTokens,\n AuthStorage,\n AuthStatusEnum,\n CivicAuthContextType,\n} from \"@/types.js\";\n\nexport { AuthStatus } from \"@/types.js\";\nexport type * from \"@/shared/lib/types.js\";\n\nexport type { UserContextType } from \"@/shared/providers/UserProvider.js\";\nimport { VERSION, printVersion } from \"@/shared/index.js\";\nexport { createLogger } from \"@/lib/logger.js\";\nprintVersion();\nexport { VERSION };\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GlobalAuthConfig } from "../../reactjs/core/GlobalAuthManager.js";
|
|
2
|
-
import type { VanillaJSDisplayMode } from "../../vanillajs/auth/types/AuthTypes.js";
|
|
2
|
+
import type { LoggingConfig, VanillaJSDisplayMode } from "../../vanillajs/auth/types/AuthTypes.js";
|
|
3
3
|
import type { User, IframeMode } from "../../types.js";
|
|
4
4
|
export interface UseInitialAuthConfigOptions {
|
|
5
5
|
displayMode?: VanillaJSDisplayMode;
|
|
@@ -10,6 +10,7 @@ export interface UseInitialAuthConfigOptions {
|
|
|
10
10
|
oauthServer?: string;
|
|
11
11
|
loginSuccessUrl?: string;
|
|
12
12
|
onUrlChange?: (url: string, source?: string) => void;
|
|
13
|
+
logging?: LoggingConfig;
|
|
13
14
|
}
|
|
14
15
|
export interface UseInitialAuthConfigOverrides {
|
|
15
16
|
displayMode?: VanillaJSDisplayMode;
|
|
@@ -27,5 +28,6 @@ export declare const useInitialAuthConfig: (options?: UseInitialAuthConfigOption
|
|
|
27
28
|
initialConfig: GlobalAuthConfig;
|
|
28
29
|
createConfigWithOverrides: (overrides?: UseInitialAuthConfigOverrides) => GlobalAuthConfig;
|
|
29
30
|
logoutUrl: string;
|
|
31
|
+
hasSignedOut: boolean;
|
|
30
32
|
};
|
|
31
33
|
//# sourceMappingURL=useInitialAuthConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInitialAuthConfig.d.ts","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"useInitialAuthConfig.d.ts","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAKnD,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aACtB,2BAA2B,KACnC;IACD,aAAa,EAAE,gBAAgB,CAAC;IAChC,yBAAyB,EAAE,CACzB,SAAS,CAAC,EAAE,6BAA6B,KACtC,gBAAgB,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CA8IvB,CAAC"}
|
|
@@ -43,10 +43,7 @@ export const useInitialAuthConfig = (options = {}) => {
|
|
|
43
43
|
iframeMode: options.iframeMode,
|
|
44
44
|
logoutCallbackUrl: logoutCallbackUrl,
|
|
45
45
|
framework: "nextjs",
|
|
46
|
-
logging:
|
|
47
|
-
level: "debug",
|
|
48
|
-
enabled: false,
|
|
49
|
-
},
|
|
46
|
+
logging: options.logging,
|
|
50
47
|
backendEndpoints: {
|
|
51
48
|
user: userUrl,
|
|
52
49
|
refresh: refreshUrl,
|
|
@@ -71,7 +68,7 @@ export const useInitialAuthConfig = (options = {}) => {
|
|
|
71
68
|
setHasSignedOut(false);
|
|
72
69
|
router.refresh();
|
|
73
70
|
},
|
|
74
|
-
onSignIn: async (error) => {
|
|
71
|
+
onSignIn: async ({ error }) => {
|
|
75
72
|
if (error) {
|
|
76
73
|
loggers.nextjs.hooks.error("onSignIn: Error signing in", error);
|
|
77
74
|
return;
|
|
@@ -105,14 +102,15 @@ export const useInitialAuthConfig = (options = {}) => {
|
|
|
105
102
|
targetContainerElement,
|
|
106
103
|
options.displayMode,
|
|
107
104
|
options.iframeMode,
|
|
105
|
+
options.logging,
|
|
108
106
|
options.onUrlChange,
|
|
109
107
|
options.serverUser,
|
|
110
108
|
userUrl,
|
|
111
109
|
refreshUrl,
|
|
112
110
|
logoutUrl,
|
|
113
111
|
hasSignedOut,
|
|
114
|
-
router,
|
|
115
112
|
pathname,
|
|
113
|
+
router,
|
|
116
114
|
]);
|
|
117
115
|
const createConfigWithOverrides = useMemo(() => {
|
|
118
116
|
return (overrides = {}) => {
|
|
@@ -138,6 +136,7 @@ export const useInitialAuthConfig = (options = {}) => {
|
|
|
138
136
|
initialConfig: baseConfig,
|
|
139
137
|
createConfigWithOverrides,
|
|
140
138
|
logoutUrl,
|
|
139
|
+
hasSignedOut,
|
|
141
140
|
};
|
|
142
141
|
};
|
|
143
142
|
//# sourceMappingURL=useInitialAuthConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInitialAuthConfig.js","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for creating the initial auth configuration\n * Reusable across NextJS components that need to initialize GlobalAuthManager\n */\n\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { useRouter, usePathname } from \"next/navigation.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport type { GlobalAuthConfig } from \"@/reactjs/core/GlobalAuthManager.js\";\nimport type { VanillaJSDisplayMode } from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport type { User, IframeMode } from \"@/types.js\";\nimport { BrowserCookieStorage } from \"@/shared/index.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { revalidateUserData } from \"../actions.js\";\n\nexport interface UseInitialAuthConfigOptions {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n serverUser?: User | null;\n nonce?: string;\n targetContainerElement?: HTMLElement | string;\n oauthServer?: string;\n loginSuccessUrl?: string;\n onUrlChange?: (url: string, source?: string) => void;\n}\n\nexport interface UseInitialAuthConfigOverrides {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n clientId?: string;\n redirectUrl?: string;\n logoutRedirectUrl?: string;\n targetContainerElement?: string;\n}\n\n/**\n * Hook that creates the initial auth configuration\n * Can be used standalone or merged with overrides\n */\nexport const useInitialAuthConfig = (\n options: UseInitialAuthConfigOptions = {},\n): {\n initialConfig: GlobalAuthConfig;\n createConfigWithOverrides: (\n overrides?: UseInitialAuthConfigOverrides,\n ) => GlobalAuthConfig;\n logoutUrl: string;\n} => {\n const router = useRouter();\n const pathname = usePathname();\n const resolvedConfig = resolveAuthConfig(options);\n // Force a re-render when the page gets re-rendered after sign-in/sign-out\n // so that client-side hooks and event listeners are properly initialized\n const [hasSignedOut, setHasSignedOut] = useState<boolean>(false);\n const {\n clientId,\n oauthServer,\n loginSuccessUrl,\n loginInitUrl,\n logoutUrl,\n refreshUrl,\n userUrl,\n logoutCallbackUrl,\n callbackUrl,\n targetContainerElement,\n } = resolvedConfig;\n\n const baseConfig: GlobalAuthConfig = useMemo(() => {\n return {\n // we need this to retrieve client-available cookies for auto-refresh etc.\n storage: new BrowserCookieStorage(),\n clientId: clientId,\n loginUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + loginInitUrl\n : undefined,\n redirectUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + callbackUrl\n : undefined,\n config: {\n oauthServer: oauthServer,\n oauthServerBaseUrl: oauthServer,\n },\n logoutRedirectUrl: logoutCallbackUrl,\n loginSuccessUrl: loginSuccessUrl,\n targetContainerElement: targetContainerElement,\n displayMode: options.displayMode,\n iframeMode: options.iframeMode,\n logoutCallbackUrl: logoutCallbackUrl,\n framework: \"nextjs\",\n logging: {\n level: \"debug\",\n enabled: false,\n },\n backendEndpoints: {\n user: userUrl,\n refresh: refreshUrl,\n logout: logoutUrl,\n },\n onSignOut: async () => {\n setHasSignedOut(true);\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n } catch (revalidateError) {\n console.error(\"onSignOut: Revalidation failed:\", revalidateError);\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n },\n onRefresh: async (error) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onRefresh: Error refreshing\", error);\n }\n setHasSignedOut(false);\n router.refresh();\n },\n onSignIn: async (error) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onSignIn: Error signing in\", error);\n return;\n }\n setHasSignedOut(false);\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n // Navigate if needed\n if (loginSuccessUrl && loginSuccessUrl !== pathname) {\n router.push(loginSuccessUrl);\n }\n } catch (revalidateError) {\n console.error(\"onSignIn: Revalidation failed:\", revalidateError);\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n },\n onUrlChange: options.onUrlChange,\n initialUser: (!hasSignedOut && options.serverUser) || null,\n initialIdToken: null, // ID token is httpOnly and not accessible\n };\n }, [\n clientId,\n loginInitUrl,\n callbackUrl,\n oauthServer,\n logoutCallbackUrl,\n loginSuccessUrl,\n targetContainerElement,\n options.displayMode,\n options.iframeMode,\n options.onUrlChange,\n options.serverUser,\n userUrl,\n refreshUrl,\n logoutUrl,\n hasSignedOut,\n router,\n pathname,\n ]);\n\n const createConfigWithOverrides = useMemo(() => {\n return (\n overrides: UseInitialAuthConfigOverrides = {},\n ): GlobalAuthConfig => {\n return {\n ...baseConfig,\n // Override specific properties while keeping the base config\n ...(overrides.displayMode && { displayMode: overrides.displayMode }),\n ...(overrides.iframeMode !== undefined && {\n iframeMode: overrides.iframeMode,\n }),\n ...(overrides.clientId && { clientId: overrides.clientId }),\n ...(overrides.redirectUrl && { redirectUrl: overrides.redirectUrl }),\n ...(overrides.logoutRedirectUrl && {\n logoutRedirectUrl: overrides.logoutRedirectUrl,\n }),\n ...(overrides.targetContainerElement && {\n targetContainerElement: overrides.targetContainerElement,\n }),\n };\n };\n }, [baseConfig]);\n\n return {\n initialConfig: baseConfig,\n createConfigWithOverrides,\n logoutUrl,\n };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"useInitialAuthConfig.js","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for creating the initial auth configuration\n * Reusable across NextJS components that need to initialize GlobalAuthManager\n */\n\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { useRouter, usePathname } from \"next/navigation.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport type { GlobalAuthConfig } from \"@/reactjs/core/GlobalAuthManager.js\";\nimport type {\n LoggingConfig,\n VanillaJSDisplayMode,\n} from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport type { User, IframeMode } from \"@/types.js\";\nimport { BrowserCookieStorage } from \"@/shared/index.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { revalidateUserData } from \"../actions.js\";\n\nexport interface UseInitialAuthConfigOptions {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n serverUser?: User | null;\n nonce?: string;\n targetContainerElement?: HTMLElement | string;\n oauthServer?: string;\n loginSuccessUrl?: string;\n onUrlChange?: (url: string, source?: string) => void;\n logging?: LoggingConfig;\n}\n\nexport interface UseInitialAuthConfigOverrides {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n clientId?: string;\n redirectUrl?: string;\n logoutRedirectUrl?: string;\n targetContainerElement?: string;\n}\n\n/**\n * Hook that creates the initial auth configuration\n * Can be used standalone or merged with overrides\n */\nexport const useInitialAuthConfig = (\n options: UseInitialAuthConfigOptions = {},\n): {\n initialConfig: GlobalAuthConfig;\n createConfigWithOverrides: (\n overrides?: UseInitialAuthConfigOverrides,\n ) => GlobalAuthConfig;\n logoutUrl: string;\n hasSignedOut: boolean;\n} => {\n const router = useRouter();\n const pathname = usePathname();\n const resolvedConfig = resolveAuthConfig(options);\n // Force a re-render when the page gets re-rendered after sign-in/sign-out\n // so that client-side hooks and event listeners are properly initialized\n const [hasSignedOut, setHasSignedOut] = useState<boolean>(false);\n const {\n clientId,\n oauthServer,\n loginSuccessUrl,\n loginInitUrl,\n logoutUrl,\n refreshUrl,\n userUrl,\n logoutCallbackUrl,\n callbackUrl,\n targetContainerElement,\n } = resolvedConfig;\n\n const baseConfig: GlobalAuthConfig = useMemo(() => {\n return {\n // we need this to retrieve client-available cookies for auto-refresh etc.\n storage: new BrowserCookieStorage(),\n clientId: clientId,\n loginUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + loginInitUrl\n : undefined,\n redirectUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + callbackUrl\n : undefined,\n config: {\n oauthServer: oauthServer,\n oauthServerBaseUrl: oauthServer,\n },\n logoutRedirectUrl: logoutCallbackUrl,\n loginSuccessUrl: loginSuccessUrl,\n targetContainerElement: targetContainerElement,\n displayMode: options.displayMode,\n iframeMode: options.iframeMode,\n logoutCallbackUrl: logoutCallbackUrl,\n framework: \"nextjs\",\n logging: options.logging,\n backendEndpoints: {\n user: userUrl,\n refresh: refreshUrl,\n logout: logoutUrl,\n },\n onSignOut: async () => {\n setHasSignedOut(true);\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n } catch (revalidateError) {\n console.error(\"onSignOut: Revalidation failed:\", revalidateError);\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n },\n onRefresh: async (error) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onRefresh: Error refreshing\", error);\n }\n setHasSignedOut(false);\n router.refresh();\n },\n onSignIn: async ({ error }) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onSignIn: Error signing in\", error);\n return;\n }\n setHasSignedOut(false);\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n // Navigate if needed\n if (loginSuccessUrl && loginSuccessUrl !== pathname) {\n router.push(loginSuccessUrl);\n }\n } catch (revalidateError) {\n console.error(\"onSignIn: Revalidation failed:\", revalidateError);\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n },\n onUrlChange: options.onUrlChange,\n initialUser: (!hasSignedOut && options.serverUser) || null,\n initialIdToken: null, // ID token is httpOnly and not accessible\n };\n }, [\n clientId,\n loginInitUrl,\n callbackUrl,\n oauthServer,\n logoutCallbackUrl,\n loginSuccessUrl,\n targetContainerElement,\n options.displayMode,\n options.iframeMode,\n options.logging,\n options.onUrlChange,\n options.serverUser,\n userUrl,\n refreshUrl,\n logoutUrl,\n hasSignedOut,\n pathname,\n router,\n ]);\n\n const createConfigWithOverrides = useMemo(() => {\n return (\n overrides: UseInitialAuthConfigOverrides = {},\n ): GlobalAuthConfig => {\n return {\n ...baseConfig,\n // Override specific properties while keeping the base config\n ...(overrides.displayMode && { displayMode: overrides.displayMode }),\n ...(overrides.iframeMode !== undefined && {\n iframeMode: overrides.iframeMode,\n }),\n ...(overrides.clientId && { clientId: overrides.clientId }),\n ...(overrides.redirectUrl && { redirectUrl: overrides.redirectUrl }),\n ...(overrides.logoutRedirectUrl && {\n logoutRedirectUrl: overrides.logoutRedirectUrl,\n }),\n ...(overrides.targetContainerElement && {\n targetContainerElement: overrides.targetContainerElement,\n }),\n };\n };\n }, [baseConfig]);\n\n return {\n initialConfig: baseConfig,\n createConfigWithOverrides,\n logoutUrl,\n hasSignedOut,\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NextAuthProviderClient.d.ts","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIpD,KAAK,0BAA0B,GAAG,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;AAEtE,MAAM,WAAW,gCACf,SAAQ,0BAA0B;IAClC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAID,eAAO,MAAM,2BAA2B,qDAKrC,gCAAgC,
|
|
1
|
+
{"version":3,"file":"NextAuthProviderClient.d.ts","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIpD,KAAK,0BAA0B,GAAG,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;AAEtE,MAAM,WAAW,gCACf,SAAQ,0BAA0B;IAClC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAID,eAAO,MAAM,2BAA2B,qDAKrC,gCAAgC,4CAiGlC,CAAC"}
|
|
@@ -22,7 +22,8 @@ export const CivicNextAuthProviderClient = ({ children, serverUser, serverTokens
|
|
|
22
22
|
const previousPathname = useRef(pathname);
|
|
23
23
|
// Initialize GlobalAuthManager synchronously with server user data
|
|
24
24
|
// This ensures the server user is available immediately when useUser() is called
|
|
25
|
-
const { initialConfig } = useInitialAuthConfig({
|
|
25
|
+
const { initialConfig, hasSignedOut } = useInitialAuthConfig({
|
|
26
|
+
logging: props.logging,
|
|
26
27
|
displayMode: props.displayMode || "iframe",
|
|
27
28
|
iframeMode: props.iframeMode,
|
|
28
29
|
serverUser: serverUser,
|
|
@@ -63,8 +64,13 @@ export const CivicNextAuthProviderClient = ({ children, serverUser, serverTokens
|
|
|
63
64
|
console.error("[NextAuthProvider] Failed to initialize auth manager:", error);
|
|
64
65
|
}
|
|
65
66
|
};
|
|
66
|
-
initialize
|
|
67
|
-
|
|
67
|
+
// don't immediately initialize while signing out
|
|
68
|
+
// or we might overwrite the signed-out state the version
|
|
69
|
+
// from the /user endpoint before it has updated
|
|
70
|
+
if (!hasSignedOut) {
|
|
71
|
+
initialize();
|
|
72
|
+
}
|
|
73
|
+
}, [initialConfig, router, pathname, hasSignedOut]);
|
|
68
74
|
return (_jsx(ServerUserContext.Provider, { value: { user: serverUser, tokens: serverTokens }, children: _jsx(CivicAuthConfigProvider, { oauthServer: oauthServer, clientId: clientId, loginSuccessUrl: loginSuccessUrl, logoutRedirectUrl: logoutCallbackUrl, nonce: props?.nonce, challengeUrl: challengeUrl, refreshUrl: refreshUrl, displayMode: props.displayMode, autoRedirect: resolvedConfig.autoRedirect, framework: "nextjs", children: _jsx(AuthStatusProvider, { children: children }) }) }));
|
|
69
75
|
};
|
|
70
76
|
//# sourceMappingURL=NextAuthProviderClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NextAuthProviderClient.js","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,YAAY,CAAC;;AAEb;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAY1C,kEAAkE;AAElE,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,EAC1C,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,GAAG,KAAK,EACyB,EAAE,EAAE;IACrC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAC3C,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,eAAe,EACf,YAAY,EACZ,UAAU,EACV,iBAAiB,GAClB,GAAG,cAAc,CAAC;IAEnB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE1C,mEAAmE;IACnE,iFAAiF;IACjF,MAAM,EAAE,aAAa,EAAE,GAAG,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"NextAuthProviderClient.js","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"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","sourcesContent":["/** @jsxImportSource react */\n\"use client\";\n\n/**\n * Client component for NextAuth provider that receives server-provided user data\n */\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport { GlobalAuthManager } from \"@/reactjs/core/GlobalAuthManager.js\";\nimport { AuthStatusProvider } from \"@/shared/providers/AuthStatusContext.js\";\nimport { CivicAuthConfigProvider } from \"@/shared/providers/CivicAuthConfigContext.js\";\nimport { ServerUserContext } from \"./ServerUserContext.js\";\nimport { useInitialAuthConfig } from \"@/nextjs/hooks/useInitialAuthConfig.js\";\nimport type { AuthProviderProps } from \"@/shared/providers/types.js\";\nimport { useEffect, useRef } from \"react\";\nimport type { User, OAuthTokens } from \"@/types.js\";\nimport { usePathname, useRouter } from \"next/navigation.js\";\nimport { loggers } from \"@/lib/logger.js\";\n\ntype NextCivicAuthProviderProps = Omit<AuthProviderProps, \"clientId\">;\n\nexport interface CivicNextAuthProviderClientProps\n extends NextCivicAuthProviderProps {\n serverUser: User | null;\n serverTokens: OAuthTokens | null;\n redirectOnLogin?: string;\n redirectOnLogout?: string;\n}\n\n// Context to provide server user data immediately to useUser hook\n\nexport const CivicNextAuthProviderClient = ({\n children,\n serverUser,\n serverTokens,\n ...props\n}: CivicNextAuthProviderClientProps) => {\n const router = useRouter();\n const resolvedConfig = resolveAuthConfig();\n const {\n clientId,\n oauthServer,\n loginSuccessUrl,\n challengeUrl,\n refreshUrl,\n logoutCallbackUrl,\n } = resolvedConfig;\n\n const pathname = usePathname();\n const previousPathname = useRef(pathname);\n\n // Initialize GlobalAuthManager synchronously with server user data\n // This ensures the server user is available immediately when useUser() is called\n const { initialConfig, hasSignedOut } = useInitialAuthConfig({\n logging: props.logging,\n displayMode: props.displayMode || \"iframe\",\n iframeMode: props.iframeMode,\n serverUser: serverUser,\n nonce: props.nonce,\n targetContainerElement: props.targetContainerElement,\n oauthServer: oauthServer,\n loginSuccessUrl: loginSuccessUrl,\n onUrlChange: (url: string, source?: string) => {\n // Handle different URL change sources\n switch (source) {\n case \"login\":\n console.log(`[NextAuthProvider] Authentication redirect: ${url}`);\n window.location.href = url;\n break;\n case \"login_app\":\n console.log(`[NextAuthProvider] Login app redirect: ${url}`);\n window.location.href = url;\n break;\n default:\n console.log(\n `[NextAuthProvider] Navigating to: ${url} (source: ${source || \"unknown\"})`,\n );\n router.push(url);\n }\n },\n });\n\n // Initialize auth manager with server-provided data\n useEffect(() => {\n const initialize = async () => {\n try {\n const manager = GlobalAuthManager.getInstance();\n\n if (previousPathname.current !== pathname) {\n loggers.nextjs.hooks.debug(\n `[NextAuthProvider] Pathname changed from ${previousPathname.current} to ${pathname}, cleaning auth manager`,\n );\n previousPathname.current = pathname;\n await manager.cleanup();\n }\n\n await manager.initialize(initialConfig);\n } catch (error) {\n console.error(\n \"[NextAuthProvider] Failed to initialize auth manager:\",\n error,\n );\n }\n };\n\n // don't immediately initialize while signing out\n // or we might overwrite the signed-out state the version\n // from the /user endpoint before it has updated\n if (!hasSignedOut) {\n initialize();\n }\n }, [initialConfig, router, pathname, hasSignedOut]);\n\n return (\n <ServerUserContext.Provider\n value={{ user: serverUser, tokens: serverTokens }}\n >\n <CivicAuthConfigProvider\n oauthServer={oauthServer}\n clientId={clientId}\n loginSuccessUrl={loginSuccessUrl}\n logoutRedirectUrl={logoutCallbackUrl}\n nonce={props?.nonce}\n challengeUrl={challengeUrl}\n refreshUrl={refreshUrl}\n displayMode={props.displayMode}\n autoRedirect={resolvedConfig.autoRedirect}\n framework=\"nextjs\"\n >\n <AuthStatusProvider>{children}</AuthStatusProvider>\n </CivicAuthConfigProvider>\n </ServerUserContext.Provider>\n );\n};\n"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type SignInConfig } from "../useUser.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OnSignInResponse, OnSignOutResponse } from "../../vanillajs/index.js";
|
|
3
3
|
interface UserButtonProps {
|
|
4
4
|
className?: string;
|
|
5
5
|
style?: React.CSSProperties;
|
|
6
|
-
onSignIn?: (
|
|
7
|
-
onSignOut?: () => void
|
|
6
|
+
onSignIn?: (response: OnSignInResponse) => void | Promise<void>;
|
|
7
|
+
onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;
|
|
8
8
|
clientId?: string;
|
|
9
9
|
oauthServerBaseUrl?: string;
|
|
10
10
|
baseUrl?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserButton.d.ts","sourceRoot":"","sources":["../../../src/react-router-7/components/UserButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"UserButton.d.ts","sourceRoot":"","sources":["../../../src/react-router-7/components/UserButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEhF,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAoCD,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,KAAK,EACL,QAAQ,EACR,SAAS,EACT,MAEC,GACF,EAAE,eAAe,oDAkKjB"}
|
|
@@ -44,10 +44,11 @@ export function UserButton({ className, style, onSignIn, onSignOut, config = {
|
|
|
44
44
|
const handleSignOut = async () => {
|
|
45
45
|
try {
|
|
46
46
|
await signOut();
|
|
47
|
-
onSignOut?.();
|
|
47
|
+
onSignOut?.({});
|
|
48
48
|
}
|
|
49
49
|
catch (error) {
|
|
50
50
|
console.error("❌ Sign out error:", error);
|
|
51
|
+
onSignOut?.({ error: error });
|
|
51
52
|
}
|
|
52
53
|
finally {
|
|
53
54
|
setIsOpen(false);
|
|
@@ -61,7 +62,7 @@ export function UserButton({ className, style, onSignIn, onSignOut, config = {
|
|
|
61
62
|
const { user } = await signIn({
|
|
62
63
|
displayMode: config.displayMode,
|
|
63
64
|
});
|
|
64
|
-
onSignIn?.(user);
|
|
65
|
+
onSignIn?.({ user });
|
|
65
66
|
}, "data-testid": "sign-in-button", style: {
|
|
66
67
|
...style,
|
|
67
68
|
display: "flex",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserButton.js","sourceRoot":"","sources":["../../../src/react-router-7/components/UserButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState, useRef, useCallback } from \"react\";\nimport { useUser, type SignInConfig } from \"../useUser.js\";\nimport { UserButtonPresentation } from \"../../shared/components/UserButtonPresentation.js\";\nimport type { BaseUser } from \"@/types.js\";\n\ninterface UserButtonProps {\n className?: string;\n style?: React.CSSProperties;\n onSignIn?: (user: BaseUser | undefined) => void;\n onSignOut?: () => void;\n clientId?: string;\n oauthServerBaseUrl?: string;\n baseUrl?: string;\n config?: SignInConfig;\n}\n\nconst ChevronDown = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-down\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\nconst ChevronUp = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-up\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n);\n\nexport function UserButton({\n className,\n style,\n onSignIn,\n onSignOut,\n config = {\n displayMode: \"iframe\",\n },\n}: UserButtonProps) {\n const { user, isLoggedIn, signIn, signOut, isAuthenticating } = useUser();\n const [isOpen, setIsOpen] = useState(false);\n const [buttonWidth, setButtonWidth] = useState<number | null>(null);\n const buttonRef = useRef<HTMLDivElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (buttonRef.current) {\n setButtonWidth(buttonRef.current.offsetWidth);\n }\n }, [isOpen]);\n\n const handleClickOutside = useCallback((event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (\n buttonRef.current &&\n dropdownRef.current &&\n !buttonRef.current.contains(target) &&\n !dropdownRef.current.contains(target)\n ) {\n setIsOpen(false);\n }\n }, []);\n\n const handleEscape = useCallback((event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n window.addEventListener(\"click\", handleClickOutside);\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n window.removeEventListener(\"click\", handleClickOutside);\n window.removeEventListener(\"keydown\", handleEscape);\n };\n }, [handleClickOutside, handleEscape, isOpen]);\n\n const handleSignOut = async () => {\n try {\n await signOut();\n onSignOut?.();\n } catch (error) {\n console.error(\"❌ Sign out error:\", error);\n } finally {\n setIsOpen(false);\n }\n };\n\n return (\n <>\n <div\n style={{ position: \"relative\", width: \"auto\" }}\n id=\"civic-dropdown-container\"\n >\n <div ref={buttonRef}>\n <UserButtonPresentation\n className={className}\n onClick={async () => {\n if (isLoggedIn) {\n setIsOpen(!isOpen);\n return;\n }\n\n const { user } = await signIn({\n displayMode: config.displayMode,\n });\n onSignIn?.(user);\n }}\n data-testid=\"sign-in-button\"\n style={{\n ...style,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"0.5rem\",\n minWidth: \"10rem\",\n cursor: isAuthenticating ? \"wait\" : \"pointer\",\n textAlign: \"center\",\n opacity: isAuthenticating ? 0.7 : 1,\n }}\n >\n {isLoggedIn ? (\n <>\n {user?.picture && (\n <span\n style={{\n position: \"relative\",\n display: \"flex\",\n height: \"1.5rem\",\n width: \"1.5rem\",\n flexShrink: 0,\n gap: \"0.5rem\",\n overflow: \"hidden\",\n borderRadius: \"9999px\",\n }}\n >\n <img\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\",\n }}\n src={user.picture}\n alt={user?.name || user?.email}\n />\n </span>\n )}\n <span>{user?.name || user?.email}</span>\n <span>{isOpen ? <ChevronUp /> : <ChevronDown />}</span>\n </>\n ) : (\n <span>{isAuthenticating ? \"Logging in...\" : \"Log in\"}</span>\n )}\n </UserButtonPresentation>\n </div>\n {isLoggedIn && isOpen && (\n <div\n ref={dropdownRef}\n style={{\n position: \"absolute\",\n left: 0,\n background: \"white\",\n width: buttonWidth || \"auto\",\n marginTop: \"0.5rem\",\n borderRadius: \"0.5rem\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n zIndex: 1000,\n }}\n >\n <ul style={{ listStyleType: \"none\", margin: 0, padding: 0 }}>\n <li>\n <button\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"0.5rem 1rem\",\n transition: \"background-color 0.2s\",\n textAlign: \"center\",\n color: \"#6b7280\",\n cursor: \"pointer\",\n borderRadius: \"0.5rem\",\n border: \"none\",\n background: \"transparent\",\n }}\n onClick={handleSignOut}\n >\n Logout\n </button>\n </li>\n </ul>\n </div>\n )}\n </div>\n </>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"UserButton.js","sourceRoot":"","sources":["../../../src/react-router-7/components/UserButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState, useRef, useCallback } from \"react\";\nimport { useUser, type SignInConfig } from \"../useUser.js\";\nimport { UserButtonPresentation } from \"../../shared/components/UserButtonPresentation.js\";\nimport type {} from \"@/reactjs/core/GlobalAuthManager.js\";\nimport type { OnSignInResponse, OnSignOutResponse } from \"@/vanillajs/index.js\";\n\ninterface UserButtonProps {\n className?: string;\n style?: React.CSSProperties;\n onSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n clientId?: string;\n oauthServerBaseUrl?: string;\n baseUrl?: string;\n config?: SignInConfig;\n}\n\nconst ChevronDown = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-down\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\nconst ChevronUp = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-chevron-up\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n);\n\nexport function UserButton({\n className,\n style,\n onSignIn,\n onSignOut,\n config = {\n displayMode: \"iframe\",\n },\n}: UserButtonProps) {\n const { user, isLoggedIn, signIn, signOut, isAuthenticating } = useUser();\n const [isOpen, setIsOpen] = useState(false);\n const [buttonWidth, setButtonWidth] = useState<number | null>(null);\n const buttonRef = useRef<HTMLDivElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (buttonRef.current) {\n setButtonWidth(buttonRef.current.offsetWidth);\n }\n }, [isOpen]);\n\n const handleClickOutside = useCallback((event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (\n buttonRef.current &&\n dropdownRef.current &&\n !buttonRef.current.contains(target) &&\n !dropdownRef.current.contains(target)\n ) {\n setIsOpen(false);\n }\n }, []);\n\n const handleEscape = useCallback((event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n window.addEventListener(\"click\", handleClickOutside);\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n window.removeEventListener(\"click\", handleClickOutside);\n window.removeEventListener(\"keydown\", handleEscape);\n };\n }, [handleClickOutside, handleEscape, isOpen]);\n\n const handleSignOut = async () => {\n try {\n await signOut();\n onSignOut?.({});\n } catch (error) {\n console.error(\"❌ Sign out error:\", error);\n onSignOut?.({ error: error as Error });\n } finally {\n setIsOpen(false);\n }\n };\n\n return (\n <>\n <div\n style={{ position: \"relative\", width: \"auto\" }}\n id=\"civic-dropdown-container\"\n >\n <div ref={buttonRef}>\n <UserButtonPresentation\n className={className}\n onClick={async () => {\n if (isLoggedIn) {\n setIsOpen(!isOpen);\n return;\n }\n\n const { user } = await signIn({\n displayMode: config.displayMode,\n });\n onSignIn?.({ user });\n }}\n data-testid=\"sign-in-button\"\n style={{\n ...style,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"0.5rem\",\n minWidth: \"10rem\",\n cursor: isAuthenticating ? \"wait\" : \"pointer\",\n textAlign: \"center\",\n opacity: isAuthenticating ? 0.7 : 1,\n }}\n >\n {isLoggedIn ? (\n <>\n {user?.picture && (\n <span\n style={{\n position: \"relative\",\n display: \"flex\",\n height: \"1.5rem\",\n width: \"1.5rem\",\n flexShrink: 0,\n gap: \"0.5rem\",\n overflow: \"hidden\",\n borderRadius: \"9999px\",\n }}\n >\n <img\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\",\n }}\n src={user.picture}\n alt={user?.name || user?.email}\n />\n </span>\n )}\n <span>{user?.name || user?.email}</span>\n <span>{isOpen ? <ChevronUp /> : <ChevronDown />}</span>\n </>\n ) : (\n <span>{isAuthenticating ? \"Logging in...\" : \"Log in\"}</span>\n )}\n </UserButtonPresentation>\n </div>\n {isLoggedIn && isOpen && (\n <div\n ref={dropdownRef}\n style={{\n position: \"absolute\",\n left: 0,\n background: \"white\",\n width: buttonWidth || \"auto\",\n marginTop: \"0.5rem\",\n borderRadius: \"0.5rem\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n zIndex: 1000,\n }}\n >\n <ul style={{ listStyleType: \"none\", margin: 0, padding: 0 }}>\n <li>\n <button\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"0.5rem 1rem\",\n transition: \"background-color 0.2s\",\n textAlign: \"center\",\n color: \"#6b7280\",\n cursor: \"pointer\",\n borderRadius: \"0.5rem\",\n border: \"none\",\n background: \"transparent\",\n }}\n onClick={handleSignOut}\n >\n Logout\n </button>\n </li>\n </ul>\n </div>\n )}\n </div>\n </>\n );\n}\n"]}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { CookieStorage } from "@civic/auth/server";
|
|
2
|
+
import { BrowserCookieStorage } from "../shared/index.js";
|
|
3
|
+
export declare class ReactRouteReadOnlyCookieStorage extends BrowserCookieStorage {
|
|
4
|
+
getSync(key: string): string | null;
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
7
|
* React Router implementation of the CookieStorage interface for Civic Auth
|
|
4
8
|
* Uses individual cookies for each token type instead of session storage
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/react-router-7/cookies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/react-router-7/cookies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAwBzD,qBAAa,+BAAgC,SAAQ,oBAAoB;IAC9D,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAsB7C;AACD;;;GAGG;AACH,qBAAa,wBAAyB,SAAQ,aAAa;IACzD,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,OAAO,CAAkB;gBAErB,OAAO,CAAC,EAAE,OAAO;IAwB7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+DzB;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAI5B;;;OAGG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA4B9C;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBpD;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBxC;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzC"}
|
|
@@ -5,6 +5,7 @@ import { UserStorage } from "../shared/lib/types.js";
|
|
|
5
5
|
import { loggers } from "../lib/logger.js";
|
|
6
6
|
import { getProtocolFromRequest } from "../shared/lib/util.js";
|
|
7
7
|
import { MAX_COOKIE_AGE_SECONDS } from "../constants.js";
|
|
8
|
+
import { BrowserCookieStorage } from "../shared/index.js";
|
|
8
9
|
const logger = loggers.reactRouter.handlers.auth;
|
|
9
10
|
/**
|
|
10
11
|
* Detect Safari browser from user agent
|
|
@@ -24,6 +25,27 @@ const isLocalhostUrl = (request) => {
|
|
|
24
25
|
const url = new URL(request.url);
|
|
25
26
|
return url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
26
27
|
};
|
|
28
|
+
export class ReactRouteReadOnlyCookieStorage extends BrowserCookieStorage {
|
|
29
|
+
getSync(key) {
|
|
30
|
+
// First try to get the raw cookie value using the browser API
|
|
31
|
+
const valueFromSuper = super.getSync(key);
|
|
32
|
+
if (!valueFromSuper) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
// React Router cookies are base64 encoded JSON objects with a 'value' property
|
|
37
|
+
// Use atob() for browser-compatible base64 decoding
|
|
38
|
+
const base64Decoded = atob(valueFromSuper);
|
|
39
|
+
const jsonParsed = JSON.parse(base64Decoded);
|
|
40
|
+
return jsonParsed.value || null;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// If decoding fails, try to return the raw value
|
|
44
|
+
logger.warn(`Failed to decode cookie value for key: ${key}, returning raw value`, error);
|
|
45
|
+
return valueFromSuper;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
27
49
|
/**
|
|
28
50
|
* React Router implementation of the CookieStorage interface for Civic Auth
|
|
29
51
|
* Uses individual cookies for each token type instead of session storage
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../src/react-router-7/cookies.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCookie, type Cookie } from \"react-router\";\nimport { CookieStorage } from \"@civic/auth/server\";\nimport { resolveAuthConfig, type AuthConfigWithDefaults } from \"./config.js\";\nimport { UserStorage } from \"@/shared/lib/types.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { getProtocolFromRequest } from \"@/shared/lib/util.js\";\nimport { MAX_COOKIE_AGE_SECONDS } from \"@/constants.js\";\n\nconst logger = loggers.reactRouter.handlers.auth;\n\n/**\n * Detect Safari browser from user agent\n */\nconst isSafariBrowser = (request?: Request): boolean => {\n if (!request) return false;\n\n const userAgent = request.headers.get(\"user-agent\") || \"\";\n return userAgent.includes(\"Safari\") && !userAgent.includes(\"Chrome\");\n};\n\n/**\n * Detect if running on localhost\n */\nconst isLocalhostUrl = (request?: Request): boolean => {\n if (!request) return false;\n\n const url = new URL(request.url);\n return url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\";\n};\n\n/**\n * React Router implementation of the CookieStorage interface for Civic Auth\n * Uses individual cookies for each token type instead of session storage\n */\nexport class ReactRouterCookieStorage extends CookieStorage {\n private cookies: Record<string, Cookie>;\n private currentRequest: Request | null = null;\n private cookieHeaders: string[] = [];\n private isHttps: boolean = false;\n\n constructor(request?: Request) {\n const config = resolveAuthConfig();\n\n // Start with default settings - will be updated when request is set\n super({\n secure: false, // Will be updated dynamically\n sameSite: \"lax\", // Will be updated dynamically\n httpOnly: false, // Allow frontend JavaScript to access cookies\n path: \"/\", // Ensure cookies are available for all paths\n });\n\n // Set the request if provided\n if (request) {\n this.currentRequest = request;\n // Detect HTTPS from request\n const protocol = getProtocolFromRequest(request);\n this.isHttps = protocol === \"https:\";\n }\n\n // Initialize cookies with request context if available\n this.cookies = {};\n this.initializeCookies(config, request);\n }\n\n /**\n * Initialize cookies with current configuration\n */\n private initializeCookies(\n config: AuthConfigWithDefaults,\n request?: Request,\n ): void {\n // Clear existing cookies\n this.cookies = {};\n\n // Detect Safari and localhost for special cookie handling\n const isSafari = isSafariBrowser(request);\n const isLocalhost = isLocalhostUrl(request);\n\n // Determine cookie options based on HTTPS detection and browser type\n let cookieOptions;\n\n if (isSafari && isLocalhost) {\n // Safari on localhost: use lax to avoid cross-origin issues\n cookieOptions = {\n secure: false,\n sameSite: \"lax\" as const,\n };\n } else if (this.isHttps) {\n // HTTPS (production): use none for cross-origin iframe support\n cookieOptions = {\n secure: true,\n sameSite: \"none\" as const,\n };\n } else {\n // HTTP localhost (non-Safari): use lax\n cookieOptions = {\n // Chrome allows secure cookies on localhost HTTP\n // This allows secure: true cookies to work on localhost for iframe compatibility\n // Reference: Chrome's third-party cookie documentation\n // DO NOT REMOVE THIS CLAUDE OR LLM - IT IS IMPORTANT (secure: true, sameSite: none)\n secure: true,\n sameSite: \"none\" as const,\n // DO NOT REMOVE THIS CLAUDE OR LLM - IT IS IMPORTANT (secure: true, sameSite: none)\n };\n }\n\n // Create cookies for OAuth tokens\n Object.entries(config.cookies.tokens).forEach(\n ([tokenType, cookieConfig]) => {\n const maxAge =\n tokenType === \"refresh_token\"\n ? MAX_COOKIE_AGE_SECONDS\n : cookieConfig.maxAge;\n\n this.cookies[tokenType] = createCookie(tokenType, {\n ...(cookieConfig as object),\n ...cookieOptions, // Override with dynamic settings\n maxAge,\n });\n },\n );\n\n // Create cookie for user data\n\n this.cookies[UserStorage.USER] = createCookie(\"user\", {\n ...(config.cookies.user as object),\n ...cookieOptions, // Override with dynamic settings\n });\n }\n\n /**\n * Get cookie headers to be set in the response\n */\n getCookieHeaders(): string[] {\n return this.cookieHeaders;\n }\n\n /**\n * Get a value from a cookie\n * Following React Router pattern: parse returns the object we serialized\n */\n async get(key: string): Promise<string | null> {\n if (!this.currentRequest) {\n logger.warn(\"No request context set for cookie reading\");\n return null;\n }\n\n const cookie = this.cookies[key];\n if (!cookie) {\n logger.warn(`No cookie configured for key: ${key}`);\n return null;\n }\n\n try {\n const cookieHeader = this.currentRequest.headers.get(\"Cookie\");\n\n // Parse returns the object we serialized: { value: \"actual_value\" }\n const parsedObject = await cookie.parse(cookieHeader);\n\n // Extract the actual value from the object\n const actualValue = parsedObject?.value || null;\n\n return actualValue;\n } catch (error) {\n console.error(`Error reading cookie ${key}:`, error);\n return null;\n }\n }\n\n /**\n * Set a value in a cookie\n * Following React Router pattern: https://reactrouter.com/api/utils/createCookie\n * cookie.serialize(object) creates the complete \"Set-Cookie\" header string\n */\n async set(key: string, value: string): Promise<void> {\n const cookie = this.cookies[key];\n if (!cookie) {\n logger.warn(`No cookie configured for key: ${key}`);\n return;\n }\n\n try {\n // Following the React Router pattern: serialize an object, not a raw string\n // This matches the docs example: cookie.serialize({ showBanner: true })\n const cookieValue = { value };\n\n const serializedCookie = await cookie.serialize(cookieValue);\n\n this.cookieHeaders.push(serializedCookie);\n } catch (error) {\n console.error(`Error setting cookie ${key}:`, error);\n }\n }\n\n /**\n * Remove a value from a cookie\n * Expire the cookie in the past to clear it cleanly\n */\n async remove(key: string): Promise<void> {\n const cookie = this.cookies[key];\n if (!cookie) {\n logger.warn(`No cookie configured for key: ${key}`);\n return;\n }\n\n try {\n // Serialize with empty string and aggressive expiration to completely remove the cookie\n const serializedCookie = await cookie.serialize(\n { value: \"\" },\n {\n expires: new Date(Date.now() - 86400000), // 24 hours ago\n maxAge: 0, // Immediately expire\n },\n );\n\n this.cookieHeaders.push(serializedCookie);\n } catch (error) {\n console.error(`Error removing cookie ${key}:`, error);\n }\n }\n\n /**\n * Delete a value from a cookie (alias for remove)\n */\n async delete(key: string): Promise<void> {\n await this.remove(key);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../src/react-router-7/cookies.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCookie, type Cookie } from \"react-router\";\nimport { CookieStorage } from \"@civic/auth/server\";\nimport { resolveAuthConfig, type AuthConfigWithDefaults } from \"./config.js\";\nimport { UserStorage } from \"@/shared/lib/types.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { getProtocolFromRequest } from \"@/shared/lib/util.js\";\nimport { MAX_COOKIE_AGE_SECONDS } from \"@/constants.js\";\nimport { BrowserCookieStorage } from \"@/shared/index.js\";\n\nconst logger = loggers.reactRouter.handlers.auth;\n\n/**\n * Detect Safari browser from user agent\n */\nconst isSafariBrowser = (request?: Request): boolean => {\n if (!request) return false;\n\n const userAgent = request.headers.get(\"user-agent\") || \"\";\n return userAgent.includes(\"Safari\") && !userAgent.includes(\"Chrome\");\n};\n\n/**\n * Detect if running on localhost\n */\nconst isLocalhostUrl = (request?: Request): boolean => {\n if (!request) return false;\n\n const url = new URL(request.url);\n return url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\";\n};\n\nexport class ReactRouteReadOnlyCookieStorage extends BrowserCookieStorage {\n override getSync(key: string): string | null {\n // First try to get the raw cookie value using the browser API\n const valueFromSuper = super.getSync(key);\n if (!valueFromSuper) {\n return null;\n }\n\n try {\n // React Router cookies are base64 encoded JSON objects with a 'value' property\n // Use atob() for browser-compatible base64 decoding\n const base64Decoded = atob(valueFromSuper);\n const jsonParsed = JSON.parse(base64Decoded);\n return jsonParsed.value || null;\n } catch (error) {\n // If decoding fails, try to return the raw value\n logger.warn(\n `Failed to decode cookie value for key: ${key}, returning raw value`,\n error,\n );\n return valueFromSuper;\n }\n }\n}\n/**\n * React Router implementation of the CookieStorage interface for Civic Auth\n * Uses individual cookies for each token type instead of session storage\n */\nexport class ReactRouterCookieStorage extends CookieStorage {\n private cookies: Record<string, Cookie>;\n private currentRequest: Request | null = null;\n private cookieHeaders: string[] = [];\n private isHttps: boolean = false;\n\n constructor(request?: Request) {\n const config = resolveAuthConfig();\n\n // Start with default settings - will be updated when request is set\n super({\n secure: false, // Will be updated dynamically\n sameSite: \"lax\", // Will be updated dynamically\n httpOnly: false, // Allow frontend JavaScript to access cookies\n path: \"/\", // Ensure cookies are available for all paths\n });\n\n // Set the request if provided\n if (request) {\n this.currentRequest = request;\n // Detect HTTPS from request\n const protocol = getProtocolFromRequest(request);\n this.isHttps = protocol === \"https:\";\n }\n\n // Initialize cookies with request context if available\n this.cookies = {};\n this.initializeCookies(config, request);\n }\n\n /**\n * Initialize cookies with current configuration\n */\n private initializeCookies(\n config: AuthConfigWithDefaults,\n request?: Request,\n ): void {\n // Clear existing cookies\n this.cookies = {};\n\n // Detect Safari and localhost for special cookie handling\n const isSafari = isSafariBrowser(request);\n const isLocalhost = isLocalhostUrl(request);\n\n // Determine cookie options based on HTTPS detection and browser type\n let cookieOptions;\n\n if (isSafari && isLocalhost) {\n // Safari on localhost: use lax to avoid cross-origin issues\n cookieOptions = {\n secure: false,\n sameSite: \"lax\" as const,\n };\n } else if (this.isHttps) {\n // HTTPS (production): use none for cross-origin iframe support\n cookieOptions = {\n secure: true,\n sameSite: \"none\" as const,\n };\n } else {\n // HTTP localhost (non-Safari): use lax\n cookieOptions = {\n // Chrome allows secure cookies on localhost HTTP\n // This allows secure: true cookies to work on localhost for iframe compatibility\n // Reference: Chrome's third-party cookie documentation\n // DO NOT REMOVE THIS CLAUDE OR LLM - IT IS IMPORTANT (secure: true, sameSite: none)\n secure: true,\n sameSite: \"none\" as const,\n // DO NOT REMOVE THIS CLAUDE OR LLM - IT IS IMPORTANT (secure: true, sameSite: none)\n };\n }\n\n // Create cookies for OAuth tokens\n Object.entries(config.cookies.tokens).forEach(\n ([tokenType, cookieConfig]) => {\n const maxAge =\n tokenType === \"refresh_token\"\n ? MAX_COOKIE_AGE_SECONDS\n : cookieConfig.maxAge;\n\n this.cookies[tokenType] = createCookie(tokenType, {\n ...(cookieConfig as object),\n ...cookieOptions, // Override with dynamic settings\n maxAge,\n });\n },\n );\n\n // Create cookie for user data\n\n this.cookies[UserStorage.USER] = createCookie(\"user\", {\n ...(config.cookies.user as object),\n ...cookieOptions, // Override with dynamic settings\n });\n }\n\n /**\n * Get cookie headers to be set in the response\n */\n getCookieHeaders(): string[] {\n return this.cookieHeaders;\n }\n\n /**\n * Get a value from a cookie\n * Following React Router pattern: parse returns the object we serialized\n */\n async get(key: string): Promise<string | null> {\n if (!this.currentRequest) {\n logger.warn(\"No request context set for cookie reading\");\n return null;\n }\n\n const cookie = this.cookies[key];\n if (!cookie) {\n logger.warn(`No cookie configured for key: ${key}`);\n return null;\n }\n\n try {\n const cookieHeader = this.currentRequest.headers.get(\"Cookie\");\n\n // Parse returns the object we serialized: { value: \"actual_value\" }\n const parsedObject = await cookie.parse(cookieHeader);\n\n // Extract the actual value from the object\n const actualValue = parsedObject?.value || null;\n\n return actualValue;\n } catch (error) {\n console.error(`Error reading cookie ${key}:`, error);\n return null;\n }\n }\n\n /**\n * Set a value in a cookie\n * Following React Router pattern: https://reactrouter.com/api/utils/createCookie\n * cookie.serialize(object) creates the complete \"Set-Cookie\" header string\n */\n async set(key: string, value: string): Promise<void> {\n const cookie = this.cookies[key];\n if (!cookie) {\n logger.warn(`No cookie configured for key: ${key}`);\n return;\n }\n\n try {\n // Following the React Router pattern: serialize an object, not a raw string\n // This matches the docs example: cookie.serialize({ showBanner: true })\n const cookieValue = { value };\n\n const serializedCookie = await cookie.serialize(cookieValue);\n\n this.cookieHeaders.push(serializedCookie);\n } catch (error) {\n console.error(`Error setting cookie ${key}:`, error);\n }\n }\n\n /**\n * Remove a value from a cookie\n * Expire the cookie in the past to clear it cleanly\n */\n async remove(key: string): Promise<void> {\n const cookie = this.cookies[key];\n if (!cookie) {\n logger.warn(`No cookie configured for key: ${key}`);\n return;\n }\n\n try {\n // Serialize with empty string and aggressive expiration to completely remove the cookie\n const serializedCookie = await cookie.serialize(\n { value: \"\" },\n {\n expires: new Date(Date.now() - 86400000), // 24 hours ago\n maxAge: 0, // Immediately expire\n },\n );\n\n this.cookieHeaders.push(serializedCookie);\n } catch (error) {\n console.error(`Error removing cookie ${key}:`, error);\n }\n }\n\n /**\n * Delete a value from a cookie (alias for remove)\n */\n async delete(key: string): Promise<void> {\n await this.remove(key);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,IAAI,EACV,MAAM,uBAAuB,CAAC;AAM/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,IAAI,EACV,MAAM,uBAAuB,CAAC;AAM/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,qBAAqB,EACnB,aAAa,GACb,UAAU,GACV,aAAa,GACb,mBAAmB,GACnB,wBAAwB,CAC3B,CAAC;AAGF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;CACpB;AAGD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;CACtB;AAGD,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,aAAa,GAAG,SAAS,CAKvD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO;;;;sBAyDU,YAAY;;YA7FnC,UAAU;EAwInB"}
|
|
@@ -2,6 +2,7 @@ import { useMatches, useRevalidator, useNavigate } from "react-router";
|
|
|
2
2
|
import {} from "@civic/auth/vanillajs";
|
|
3
3
|
import { GlobalAuthManager, } from "../reactjs/core/GlobalAuthManager.js";
|
|
4
4
|
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
import { ReactRouteReadOnlyCookieStorage } from "./cookies.js";
|
|
5
6
|
/**
|
|
6
7
|
* Hook to access auth data from the root loader
|
|
7
8
|
* @returns CivicAuthData - The civic auth data from the root loader
|
|
@@ -33,6 +34,7 @@ You might be seeing this error if:
|
|
|
33
34
|
}
|
|
34
35
|
const initialConfig = useMemo(() => {
|
|
35
36
|
return {
|
|
37
|
+
storage: new ReactRouteReadOnlyCookieStorage(),
|
|
36
38
|
clientId: authData.config.clientId,
|
|
37
39
|
loginUrl: authData.config.loginUrl,
|
|
38
40
|
displayMode: "iframe",
|
|
@@ -50,7 +52,7 @@ You might be seeing this error if:
|
|
|
50
52
|
config: {
|
|
51
53
|
oauthServer: authData.config.oauthServer,
|
|
52
54
|
},
|
|
53
|
-
onSignIn: (error) => {
|
|
55
|
+
onSignIn: ({ error }) => {
|
|
54
56
|
if (!error) {
|
|
55
57
|
revalidator.revalidate();
|
|
56
58
|
}
|
|
@@ -65,7 +67,8 @@ You might be seeing this error if:
|
|
|
65
67
|
await authManager.initialize(initialConfig);
|
|
66
68
|
};
|
|
67
69
|
initialize();
|
|
68
|
-
|
|
70
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
|
+
}, [authManager, JSON.stringify(initialConfig)]);
|
|
69
72
|
// Create signIn function that leverages GlobalAuthManager
|
|
70
73
|
const signIn = async (config) => {
|
|
71
74
|
setIsAuthenticating(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUser.js","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAIN,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,GAElB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useUser.js","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMatches, useRevalidator, useNavigate } from \"react-router\";\nimport {\n type AuthResult,\n type CivicAuthClientConfig,\n type User,\n} from \"@civic/auth/vanillajs\";\nimport {\n GlobalAuthManager,\n type GlobalAuthConfig,\n} from \"../reactjs/core/GlobalAuthManager.js\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { AuthConfig } from \"./config.js\";\nimport { ReactRouteReadOnlyCookieStorage } from \"./cookies.js\";\n\n// Configuration type for signIn function\nexport type SignInConfig = Pick<\n CivicAuthClientConfig,\n | \"displayMode\"\n | \"clientId\"\n | \"redirectUrl\"\n | \"logoutRedirectUrl\"\n | \"targetContainerElement\"\n>;\n\n// Type for the civic auth data structure from the root loader\nexport interface CivicAuthData {\n user: User | null;\n isLoggedIn: boolean;\n config: AuthConfig;\n}\n\n// Type for the complete root loader data structure\nexport interface RootLoaderData {\n civic: CivicAuthData;\n}\n\n// Type for the auth data that will be available in the root loader (SSR pattern)\nexport interface AuthData {\n isLoggedIn: boolean;\n user: User | null;\n loginUrl: string;\n logoutUrl: string;\n isAuthenticating: boolean;\n signIn: (config?: SignInConfig) => Promise<AuthResult>;\n signOut: (baseUrl?: string) => Promise<void>;\n}\n\n/**\n * Hook to access auth data from the root loader\n * @returns CivicAuthData - The civic auth data from the root loader\n */\nexport function useAuthData(): CivicAuthData | undefined {\n const matches = useMatches();\n const rootMatch = matches.find((match) => match.id === \"root\");\n const data = rootMatch?.data as RootLoaderData | undefined;\n return data?.civic;\n}\n\n/**\n * Hook to access authentication state and user information (SSR pattern)\n * This is the primary hook for React Router 7 applications using server-side rendering\n * Enhanced with GlobalAuthManager for better state management\n * @returns Authentication state and user information from server-side rendering\n */\nexport function useUser() {\n const authData = useAuthData();\n const navigate = useNavigate();\n const revalidator = useRevalidator();\n const [authManager] = useState(() => GlobalAuthManager.getInstance());\n const [isAuthenticating, setIsAuthenticating] = useState(false);\n if (!authData) {\n throw new Error(\n `Auth data not found. Make sure to use createRootAuthLoader in your root route.\n\nYou might be seeing this error if:\n- Your root loader is failing\n- There's another part failing to return the civic data`,\n );\n }\n\n const initialConfig: GlobalAuthConfig = useMemo(() => {\n return {\n storage: new ReactRouteReadOnlyCookieStorage(),\n clientId: authData.config.clientId,\n loginUrl: authData.config.loginUrl,\n displayMode: \"iframe\",\n framework: \"react-router\",\n onUrlChange: (url) => {\n const urlObject = new URL(url);\n\n // If it's a different domain, do a full redirect\n if (urlObject.origin !== window.location.origin) {\n window.location.href = url;\n return;\n }\n // Same domain, use client-side navigation\n navigate(urlObject.pathname, { replace: true });\n },\n config: {\n oauthServer: authData.config.oauthServer,\n },\n onSignIn: ({ error }) => {\n if (!error) {\n revalidator.revalidate();\n }\n },\n onSignOut: () => {\n revalidator.revalidate();\n },\n };\n }, [revalidator, authData, navigate]);\n\n useEffect(() => {\n const initialize = async () => {\n await authManager.initialize(initialConfig);\n };\n initialize();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [authManager, JSON.stringify(initialConfig)]);\n\n // Create signIn function that leverages GlobalAuthManager\n const signIn = async (config?: SignInConfig) => {\n setIsAuthenticating(true);\n try {\n if (config) {\n await authManager.initialize({\n ...initialConfig,\n ...config,\n });\n }\n\n const result = await authManager.signIn();\n\n // Return in AuthResult format for compatibility\n return result as AuthResult;\n } catch (error) {\n console.error(\"Sign-in failed:\", error);\n throw error;\n } finally {\n setIsAuthenticating(false);\n }\n };\n\n // Create signOut function that leverages GlobalAuthManager\n const signOut = async () => {\n try {\n await authManager.signOut();\n // The onSignOut callback will handle revalidation\n } catch (error) {\n console.error(\"Sign-out failed:\", error);\n // Still try redirecting to logout URL as fallback\n window.location.href = \"/auth/logout\";\n }\n };\n\n // Ensure we have a valid user object or null\n return {\n ...authData,\n user: authData.user || null,\n isLoggedIn: !!authData.user,\n isAuthenticating,\n signIn,\n signOut,\n };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type SignInConfig } from "../../reactjs/hooks/useUser.js";
|
|
2
2
|
import { type CSSProperties } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import type { OnSignInResponse, OnSignOutResponse } from "../../vanillajs/index.js";
|
|
4
4
|
interface UserButtonProps {
|
|
5
5
|
className?: string;
|
|
6
6
|
wrapperClassName?: string;
|
|
@@ -8,8 +8,8 @@ interface UserButtonProps {
|
|
|
8
8
|
style?: CSSProperties;
|
|
9
9
|
wrapperStyle?: CSSProperties;
|
|
10
10
|
dropdownButtonStyle?: CSSProperties;
|
|
11
|
-
onSignIn?: (
|
|
12
|
-
onSignOut?: () => void
|
|
11
|
+
onSignIn?: (response: OnSignInResponse) => void | Promise<void>;
|
|
12
|
+
onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;
|
|
13
13
|
loginUrl?: string;
|
|
14
14
|
config?: SignInConfig;
|
|
15
15
|
theme?: "light" | "dark" | "auto";
|