@civic/auth 0.0.1-beta.0 → 0.0.1-beta.10
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/README.md +36 -10
- package/dist/chunk-CRTRMMJ7.js +59 -0
- package/dist/chunk-CRTRMMJ7.js.map +1 -0
- package/dist/chunk-EAANLFR5.mjs +148 -0
- package/dist/chunk-EAANLFR5.mjs.map +1 -0
- package/dist/chunk-EGFTMH5S.mjs +214 -0
- package/dist/chunk-EGFTMH5S.mjs.map +1 -0
- package/dist/chunk-KCSGIIPA.js +214 -0
- package/dist/chunk-KCSGIIPA.js.map +1 -0
- package/dist/chunk-MVO4UZ2A.js +148 -0
- package/dist/chunk-MVO4UZ2A.js.map +1 -0
- package/dist/chunk-PMDIR5XE.mjs +502 -0
- package/dist/chunk-PMDIR5XE.mjs.map +1 -0
- package/dist/chunk-RGHW4PYM.mjs +59 -0
- package/dist/chunk-RGHW4PYM.mjs.map +1 -0
- package/dist/chunk-YNLXRD5L.js +502 -0
- package/dist/chunk-YNLXRD5L.js.map +1 -0
- package/dist/{index-yT0eVchS.d.mts → index-Bfi0hVMZ.d.mts} +14 -8
- package/dist/{index-yT0eVchS.d.ts → index-Bfi0hVMZ.d.ts} +14 -8
- package/dist/index.css +66 -66
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/nextjs.d.mts +220 -4
- package/dist/nextjs.d.ts +220 -4
- package/dist/nextjs.js +228 -104
- package/dist/nextjs.js.map +1 -1
- package/dist/nextjs.mjs +228 -82
- package/dist/nextjs.mjs.map +1 -1
- package/dist/react.d.mts +60 -24
- package/dist/react.d.ts +60 -24
- package/dist/react.js +759 -895
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +726 -828
- package/dist/react.mjs.map +1 -1
- package/dist/server.d.mts +56 -0
- package/dist/server.d.ts +56 -0
- package/dist/server.js +20 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +20 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +20 -6
package/dist/react.mjs
CHANGED
|
@@ -1,65 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
target[prop] = source[prop];
|
|
26
|
-
if (source != null && __getOwnPropSymbols)
|
|
27
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
28
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
29
|
-
target[prop] = source[prop];
|
|
30
|
-
}
|
|
31
|
-
return target;
|
|
32
|
-
};
|
|
33
|
-
var __async = (__this, __arguments, generator) => {
|
|
34
|
-
return new Promise((resolve, reject) => {
|
|
35
|
-
var fulfilled = (value) => {
|
|
36
|
-
try {
|
|
37
|
-
step(generator.next(value));
|
|
38
|
-
} catch (e) {
|
|
39
|
-
reject(e);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
var rejected = (value) => {
|
|
43
|
-
try {
|
|
44
|
-
step(generator.throw(value));
|
|
45
|
-
} catch (e) {
|
|
46
|
-
reject(e);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
50
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
51
|
-
});
|
|
52
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
resolveAuthConfig,
|
|
3
|
+
resolveCallbackUrl
|
|
4
|
+
} from "./chunk-EAANLFR5.mjs";
|
|
5
|
+
import {
|
|
6
|
+
BrowserAuthenticationInitiator,
|
|
7
|
+
BrowserAuthenticationService,
|
|
8
|
+
BrowserPublicClientPKCEProducer,
|
|
9
|
+
ConfidentialClientPKCEConsumer,
|
|
10
|
+
DEFAULT_SCOPES,
|
|
11
|
+
GenericUserSession,
|
|
12
|
+
IFRAME_ID,
|
|
13
|
+
LocalStorageAdapter,
|
|
14
|
+
cn,
|
|
15
|
+
generateState,
|
|
16
|
+
getUser,
|
|
17
|
+
isWindowInIframe
|
|
18
|
+
} from "./chunk-PMDIR5XE.mjs";
|
|
19
|
+
import {
|
|
20
|
+
__async,
|
|
21
|
+
__objRest,
|
|
22
|
+
__spreadProps,
|
|
23
|
+
__spreadValues
|
|
24
|
+
} from "./chunk-RGHW4PYM.mjs";
|
|
53
25
|
|
|
54
26
|
// src/react/hooks/useUser.tsx
|
|
55
|
-
import { useContext as
|
|
27
|
+
import { useContext as useContext5 } from "react";
|
|
56
28
|
|
|
57
29
|
// src/react/providers/UserProvider.tsx
|
|
58
|
-
import { createContext } from "react";
|
|
30
|
+
import { createContext as createContext4 } from "react";
|
|
59
31
|
import { useQuery } from "@tanstack/react-query";
|
|
60
32
|
|
|
61
33
|
// src/react/hooks/useAuth.tsx
|
|
62
34
|
import { useContext } from "react";
|
|
35
|
+
|
|
36
|
+
// src/shared/AuthContext.tsx
|
|
37
|
+
import { createContext } from "react";
|
|
38
|
+
var AuthContext = createContext(null);
|
|
39
|
+
|
|
40
|
+
// src/react/hooks/useAuth.tsx
|
|
63
41
|
var useAuth = () => {
|
|
64
42
|
const context = useContext(AuthContext);
|
|
65
43
|
if (!context) {
|
|
@@ -69,96 +47,88 @@ var useAuth = () => {
|
|
|
69
47
|
};
|
|
70
48
|
|
|
71
49
|
// src/react/hooks/useToken.tsx
|
|
50
|
+
import { useContext as useContext3 } from "react";
|
|
51
|
+
|
|
52
|
+
// src/react/providers/TokenProvider.tsx
|
|
53
|
+
import { createContext as createContext3, useMemo } from "react";
|
|
54
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
55
|
+
|
|
56
|
+
// src/react/hooks/useSession.tsx
|
|
72
57
|
import { useContext as useContext2 } from "react";
|
|
73
|
-
|
|
74
|
-
|
|
58
|
+
|
|
59
|
+
// src/react/providers/SessionProvider.tsx
|
|
60
|
+
import {
|
|
61
|
+
createContext as createContext2
|
|
62
|
+
} from "react";
|
|
63
|
+
import { jsx } from "react/jsx-runtime";
|
|
64
|
+
var defaultSession = {
|
|
65
|
+
authenticated: false,
|
|
66
|
+
idToken: void 0,
|
|
67
|
+
accessToken: void 0,
|
|
68
|
+
displayMode: "iframe",
|
|
69
|
+
iframeRef: null,
|
|
70
|
+
setAuthResponseUrl: () => {
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var SessionContext = createContext2(defaultSession);
|
|
74
|
+
var SessionProvider = ({
|
|
75
|
+
children,
|
|
76
|
+
session,
|
|
77
|
+
iframeRef,
|
|
78
|
+
setAuthResponseUrl
|
|
79
|
+
}) => /* @__PURE__ */ jsx(
|
|
80
|
+
SessionContext.Provider,
|
|
81
|
+
{
|
|
82
|
+
value: __spreadProps(__spreadValues({}, session || defaultSession), { iframeRef, setAuthResponseUrl }),
|
|
83
|
+
children
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// src/react/hooks/useSession.tsx
|
|
88
|
+
var useSession = () => {
|
|
89
|
+
const context = useContext2(SessionContext);
|
|
75
90
|
if (!context) {
|
|
76
|
-
throw new Error("
|
|
91
|
+
throw new Error("useSession must be used within an SessionProvider");
|
|
77
92
|
}
|
|
78
93
|
return context;
|
|
79
94
|
};
|
|
80
95
|
|
|
81
|
-
// src/react/providers/
|
|
96
|
+
// src/react/providers/TokenProvider.tsx
|
|
82
97
|
import { parseJWT } from "oslo/jwt";
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
var
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const { isLoading: authLoading, error: authError } = useAuth();
|
|
89
|
-
const session = useSession();
|
|
90
|
-
const { forwardedTokens, idToken, accessToken, refreshToken } = useToken();
|
|
91
|
-
const { isAuthenticated, signIn, signOut } = useAuth();
|
|
92
|
-
const fetchUser = () => __async(void 0, null, function* () {
|
|
93
|
-
if (!(session == null ? void 0 : session.idToken)) {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
const parsedJWT = parseJWT(session.idToken);
|
|
97
|
-
if (!parsedJWT) {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
const user2 = parsedJWT.payload;
|
|
101
|
-
return __spreadProps(__spreadValues({}, user2), {
|
|
102
|
-
forwardedTokens,
|
|
103
|
-
idToken,
|
|
104
|
-
accessToken,
|
|
105
|
-
refreshToken
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
const {
|
|
109
|
-
data: user,
|
|
110
|
-
isLoading: userLoading,
|
|
111
|
-
error: userError,
|
|
112
|
-
refetch
|
|
113
|
-
} = useQuery({
|
|
114
|
-
queryKey: ["user", session == null ? void 0 : session.accessToken],
|
|
115
|
-
queryFn: fetchUser,
|
|
116
|
-
enabled: !!(session == null ? void 0 : session.accessToken)
|
|
117
|
-
// Only run the query if we have an access token
|
|
118
|
-
});
|
|
119
|
-
const isLoading = authLoading || userLoading;
|
|
120
|
-
const error = authError || userError;
|
|
121
|
-
return /* @__PURE__ */ jsx(
|
|
122
|
-
UserContext.Provider,
|
|
98
|
+
|
|
99
|
+
// src/lib/jwt.ts
|
|
100
|
+
var convertForwardedTokenFormat = (inputTokens) => Object.fromEntries(
|
|
101
|
+
Object.entries(inputTokens).map(([source, tokens]) => [
|
|
102
|
+
source,
|
|
123
103
|
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
error,
|
|
128
|
-
refetch,
|
|
129
|
-
isAuthenticated,
|
|
130
|
-
signIn,
|
|
131
|
-
signOut
|
|
132
|
-
},
|
|
133
|
-
children
|
|
104
|
+
idToken: tokens == null ? void 0 : tokens.id_token,
|
|
105
|
+
accessToken: tokens == null ? void 0 : tokens.access_token,
|
|
106
|
+
refreshToken: tokens == null ? void 0 : tokens.refresh_token
|
|
134
107
|
}
|
|
135
|
-
)
|
|
136
|
-
|
|
108
|
+
])
|
|
109
|
+
);
|
|
137
110
|
|
|
138
111
|
// src/react/providers/TokenProvider.tsx
|
|
139
|
-
import { createContext as createContext2, useMemo } from "react";
|
|
140
|
-
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
141
|
-
import { parseJWT as parseJWT2 } from "oslo/jwt";
|
|
142
112
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
143
|
-
var TokenContext =
|
|
113
|
+
var TokenContext = createContext3(void 0);
|
|
144
114
|
var TokenProvider = ({ children }) => {
|
|
145
115
|
const { isLoading, error: authError } = useAuth();
|
|
146
116
|
const session = useSession();
|
|
147
|
-
const
|
|
117
|
+
const queryClient3 = useQueryClient();
|
|
148
118
|
const refreshTokenMutation = useMutation({
|
|
149
119
|
mutationFn: () => __async(void 0, null, function* () {
|
|
150
120
|
throw new Error("Method not implemented.");
|
|
151
121
|
}),
|
|
152
122
|
onSuccess: () => {
|
|
153
|
-
|
|
123
|
+
queryClient3.invalidateQueries({ queryKey: ["session"] });
|
|
154
124
|
}
|
|
155
125
|
});
|
|
156
126
|
const decodeTokens = useMemo(() => {
|
|
157
127
|
if (!(session == null ? void 0 : session.idToken)) return null;
|
|
158
|
-
const parsedJWT =
|
|
128
|
+
const parsedJWT = parseJWT(session.idToken);
|
|
159
129
|
if (!parsedJWT) return null;
|
|
160
130
|
const { forwardedTokens } = parsedJWT.payload;
|
|
161
|
-
return forwardedTokens;
|
|
131
|
+
return forwardedTokens ? convertForwardedTokenFormat(forwardedTokens) : null;
|
|
162
132
|
}, [session == null ? void 0 : session.idToken]);
|
|
163
133
|
const value = useMemo(
|
|
164
134
|
() => ({
|
|
@@ -182,378 +152,93 @@ var TokenProvider = ({ children }) => {
|
|
|
182
152
|
return /* @__PURE__ */ jsx2(TokenContext.Provider, { value, children });
|
|
183
153
|
};
|
|
184
154
|
|
|
185
|
-
// src/react/
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
useMemo as useMemo2,
|
|
191
|
-
useCallback as useCallback2
|
|
192
|
-
} from "react";
|
|
193
|
-
import { useQuery as useQuery2, useMutation as useMutation2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
|
|
194
|
-
|
|
195
|
-
// src/services/UserInfoService.ts
|
|
196
|
-
var UserInfoServiceImpl = class {
|
|
197
|
-
constructor(endpoints) {
|
|
198
|
-
this.endpoints = endpoints;
|
|
199
|
-
}
|
|
200
|
-
getUserInfo(accessToken) {
|
|
201
|
-
return __async(this, null, function* () {
|
|
202
|
-
return {
|
|
203
|
-
id: "user123",
|
|
204
|
-
name: "John Doe",
|
|
205
|
-
email: "john@example.com",
|
|
206
|
-
picture: "https://example.com/john.jpg",
|
|
207
|
-
given_name: "John",
|
|
208
|
-
family_name: "Doe",
|
|
209
|
-
created_at: /* @__PURE__ */ new Date(),
|
|
210
|
-
updated_at: /* @__PURE__ */ new Date(),
|
|
211
|
-
country: "US",
|
|
212
|
-
accessToken
|
|
213
|
-
};
|
|
214
|
-
});
|
|
155
|
+
// src/react/hooks/useToken.tsx
|
|
156
|
+
var useToken = () => {
|
|
157
|
+
const context = useContext3(TokenContext);
|
|
158
|
+
if (!context) {
|
|
159
|
+
throw new Error("useToken must be used within a TokenProvider");
|
|
215
160
|
}
|
|
161
|
+
return context;
|
|
216
162
|
};
|
|
217
163
|
|
|
218
|
-
// src/
|
|
219
|
-
import {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
return {
|
|
236
|
-
jwks: openIdConfig.jwks_uri,
|
|
237
|
-
auth: openIdConfig.authorization_endpoint,
|
|
238
|
-
token: openIdConfig.token_endpoint,
|
|
239
|
-
userinfo: openIdConfig.userinfo_endpoint
|
|
240
|
-
};
|
|
241
|
-
});
|
|
242
|
-
var generateState = (displayMode) => {
|
|
243
|
-
const jsonString = JSON.stringify({
|
|
244
|
-
uuid: uuid(),
|
|
245
|
-
displayMode
|
|
164
|
+
// src/react/providers/UserProvider.tsx
|
|
165
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
166
|
+
var UserContext = createContext4(null);
|
|
167
|
+
var UserProvider = ({
|
|
168
|
+
children,
|
|
169
|
+
storage
|
|
170
|
+
}) => {
|
|
171
|
+
const { isLoading: authLoading, error: authError } = useAuth();
|
|
172
|
+
const session = useSession();
|
|
173
|
+
const { accessToken } = useToken();
|
|
174
|
+
const { signIn, signOut } = useAuth();
|
|
175
|
+
const fetchUser = () => __async(void 0, null, function* () {
|
|
176
|
+
if (!accessToken) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
const userSession = new GenericUserSession(storage);
|
|
180
|
+
return userSession.get();
|
|
246
181
|
});
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
182
|
+
const {
|
|
183
|
+
data: user,
|
|
184
|
+
isLoading: userLoading,
|
|
185
|
+
error: userError
|
|
186
|
+
} = useQuery({
|
|
187
|
+
queryKey: ["user", session == null ? void 0 : session.idToken],
|
|
188
|
+
queryFn: fetchUser,
|
|
189
|
+
enabled: !!(session == null ? void 0 : session.idToken)
|
|
190
|
+
// Only run the query if we have an access token
|
|
191
|
+
});
|
|
192
|
+
const isLoading = authLoading || userLoading;
|
|
193
|
+
const error = authError || userError;
|
|
194
|
+
return /* @__PURE__ */ jsx3(
|
|
195
|
+
UserContext.Provider,
|
|
196
|
+
{
|
|
197
|
+
value: {
|
|
198
|
+
user: user != null ? user : null,
|
|
199
|
+
isLoading,
|
|
200
|
+
error,
|
|
201
|
+
signIn,
|
|
202
|
+
signOut
|
|
203
|
+
},
|
|
204
|
+
children
|
|
269
205
|
}
|
|
270
|
-
|
|
271
|
-
return true;
|
|
272
|
-
}
|
|
273
|
-
popup.close();
|
|
274
|
-
return false;
|
|
275
|
-
};
|
|
276
|
-
var cn = (...inputs) => {
|
|
277
|
-
return twMerge(clsx(inputs));
|
|
206
|
+
);
|
|
278
207
|
};
|
|
279
208
|
|
|
280
|
-
// src/
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
this._endpoints = inputEndpoints;
|
|
290
|
-
}
|
|
291
|
-
getUserInfoService() {
|
|
292
|
-
return __async(this, null, function* () {
|
|
293
|
-
if (this._userInfoService) {
|
|
294
|
-
return this._userInfoService;
|
|
295
|
-
}
|
|
296
|
-
const endpoints = yield this.getEndpoints();
|
|
297
|
-
this._userInfoService = new UserInfoServiceImpl(endpoints);
|
|
298
|
-
return this._userInfoService;
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
getEndpoints() {
|
|
302
|
-
return __async(this, null, function* () {
|
|
303
|
-
if (this._endpoints) {
|
|
304
|
-
return this._endpoints;
|
|
305
|
-
}
|
|
306
|
-
this._endpoints = yield getOauthEndpoints(this.oauthServer);
|
|
307
|
-
return this._endpoints;
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
getOauth2Client() {
|
|
311
|
-
return __async(this, null, function* () {
|
|
312
|
-
if (this._oauth2Client) {
|
|
313
|
-
return this._oauth2Client;
|
|
314
|
-
}
|
|
315
|
-
const endpoints = yield this.getEndpoints();
|
|
316
|
-
this._oauth2Client = new OAuth2Client(
|
|
317
|
-
this.clientId,
|
|
318
|
-
endpoints.auth,
|
|
319
|
-
endpoints.token,
|
|
320
|
-
// this
|
|
321
|
-
{ redirectURI: this.redirectUrl }
|
|
322
|
-
);
|
|
323
|
-
return this._oauth2Client;
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
getSessionData() {
|
|
327
|
-
return JSON.parse(
|
|
328
|
-
localStorage.getItem(`civic-auth:${this.clientId}`) || "{}"
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
updateSessionData(data) {
|
|
332
|
-
localStorage.setItem(
|
|
333
|
-
`civic-auth:${this.clientId}`,
|
|
334
|
-
JSON.stringify(__spreadValues({}, data))
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
getAuthorizationUrl(scopes, displayMode, nonce) {
|
|
338
|
-
return __async(this, null, function* () {
|
|
339
|
-
const state = generateState(displayMode);
|
|
340
|
-
this.state = state;
|
|
341
|
-
const existingSessionData = this.getSessionData();
|
|
342
|
-
this.updateSessionData(__spreadProps(__spreadValues({}, existingSessionData), {
|
|
343
|
-
codeVerifier: this.codeVerifier,
|
|
344
|
-
displayMode
|
|
345
|
-
}));
|
|
346
|
-
const oauth2Client = yield this.getOauth2Client();
|
|
347
|
-
const oAuthUrl = yield oauth2Client.createAuthorizationURL({
|
|
348
|
-
state,
|
|
349
|
-
codeVerifier: this.codeVerifier,
|
|
350
|
-
codeChallengeMethod: "S256",
|
|
351
|
-
scopes
|
|
352
|
-
});
|
|
353
|
-
if (nonce) {
|
|
354
|
-
oAuthUrl.searchParams.append("nonce", nonce);
|
|
355
|
-
}
|
|
356
|
-
return oAuthUrl.toString();
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
// TODO fix the Window reference
|
|
360
|
-
loadAuthorizationUrl(authorizationURL, displayMode) {
|
|
361
|
-
switch (displayMode) {
|
|
362
|
-
case "iframe":
|
|
363
|
-
break;
|
|
364
|
-
case "redirect":
|
|
365
|
-
window.location.href = authorizationURL;
|
|
366
|
-
break;
|
|
367
|
-
case "new_tab":
|
|
368
|
-
window.open(authorizationURL, "_blank");
|
|
369
|
-
break;
|
|
370
|
-
case "custom_tab":
|
|
371
|
-
break;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
init() {
|
|
375
|
-
return __async(this, null, function* () {
|
|
376
|
-
this.updateSessionData({ authenticated: false });
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
determineDisplayMode(displayMode) {
|
|
380
|
-
if (isPopupBlocked() && displayMode === "iframe") {
|
|
381
|
-
displayMode = "redirect";
|
|
382
|
-
}
|
|
383
|
-
return displayMode;
|
|
384
|
-
}
|
|
385
|
-
signIn(displayMode, scopes, nonce) {
|
|
386
|
-
return __async(this, null, function* () {
|
|
387
|
-
const authorizationURL = yield this.getAuthorizationUrl(
|
|
388
|
-
scopes,
|
|
389
|
-
displayMode,
|
|
390
|
-
nonce
|
|
391
|
-
);
|
|
392
|
-
this.loadAuthorizationUrl(authorizationURL, displayMode);
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
tokenExchange(responseUrl) {
|
|
396
|
-
return __async(this, null, function* () {
|
|
397
|
-
let session = this.getSessionData();
|
|
398
|
-
if (!session.authenticated) {
|
|
399
|
-
const url = new URL(responseUrl);
|
|
400
|
-
const authorizationCode = url.searchParams.get("code");
|
|
401
|
-
const returnedState = url.searchParams.get("state");
|
|
402
|
-
if (!authorizationCode || !returnedState) {
|
|
403
|
-
throw new Error("Invalid authorization response");
|
|
404
|
-
}
|
|
405
|
-
const codeVerifier = this.getSessionData().codeVerifier;
|
|
406
|
-
const oauth2Client = yield this.getOauth2Client();
|
|
407
|
-
const tokens = yield oauth2Client.validateAuthorizationCode(
|
|
408
|
-
authorizationCode,
|
|
409
|
-
{
|
|
410
|
-
codeVerifier
|
|
411
|
-
}
|
|
412
|
-
);
|
|
413
|
-
try {
|
|
414
|
-
yield this.validateTokens(tokens);
|
|
415
|
-
} catch (error) {
|
|
416
|
-
console.error("tokenExchange tokens", { error, tokens });
|
|
417
|
-
throw new Error(
|
|
418
|
-
`OIDC tokens validation failed: ${error.message}`
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
const parsedDisplayMode = displayModeFromState(
|
|
422
|
-
returnedState,
|
|
423
|
-
session.displayMode
|
|
424
|
-
);
|
|
425
|
-
session = __spreadProps(__spreadValues({}, session), {
|
|
426
|
-
displayMode: parsedDisplayMode,
|
|
427
|
-
idToken: tokens.id_token,
|
|
428
|
-
authenticated: true,
|
|
429
|
-
state: returnedState,
|
|
430
|
-
accessToken: tokens.access_token,
|
|
431
|
-
refreshToken: tokens.refresh_token,
|
|
432
|
-
expiresIn: tokens.expires_in
|
|
433
|
-
});
|
|
434
|
-
this.updateSessionData(session);
|
|
435
|
-
}
|
|
436
|
-
if (session.displayMode === "new_tab") {
|
|
437
|
-
window.close();
|
|
438
|
-
} else if (session.displayMode === "redirect") {
|
|
439
|
-
}
|
|
440
|
-
return session;
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
refreshToken() {
|
|
444
|
-
return __async(this, null, function* () {
|
|
445
|
-
const sessionData = this.getSessionData();
|
|
446
|
-
if (!sessionData.refreshToken) {
|
|
447
|
-
throw new Error("No refresh token available");
|
|
448
|
-
}
|
|
449
|
-
const oauth2Client = yield this.getOauth2Client();
|
|
450
|
-
const tokens = yield oauth2Client.refreshAccessToken(
|
|
451
|
-
sessionData.refreshToken
|
|
452
|
-
);
|
|
453
|
-
const session = __spreadProps(__spreadValues({}, sessionData), {
|
|
454
|
-
idToken: tokens.id_token,
|
|
455
|
-
authenticated: true,
|
|
456
|
-
accessToken: tokens.access_token,
|
|
457
|
-
refreshToken: tokens.refresh_token,
|
|
458
|
-
expiresIn: tokens.expires_in
|
|
459
|
-
});
|
|
460
|
-
this.updateSessionData(session);
|
|
461
|
-
return session;
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
getUserInfo() {
|
|
465
|
-
return __async(this, null, function* () {
|
|
466
|
-
const sessionData = this.getSessionData();
|
|
467
|
-
if (!sessionData.accessToken) {
|
|
468
|
-
throw new Error("No access token available");
|
|
469
|
-
}
|
|
470
|
-
const userInfoService = yield this.getUserInfoService();
|
|
471
|
-
return userInfoService.getUserInfo(sessionData.accessToken);
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Uses the jose library to validate a JWT token using the OAuth JWKS endpoint
|
|
476
|
-
* @param {string} token
|
|
477
|
-
* @returns {Promise<jose.JWTPayload>}
|
|
478
|
-
* @throws {Error} if the token is invalid
|
|
479
|
-
*/
|
|
480
|
-
validateTokens(tokens) {
|
|
481
|
-
return __async(this, null, function* () {
|
|
482
|
-
const endpoints = yield this.getEndpoints();
|
|
483
|
-
const JWKS = jose.createRemoteJWKSet(new URL(endpoints.jwks));
|
|
484
|
-
const returnPayload = {};
|
|
485
|
-
console.log("issuer", getIssuerVariations(this.oauthServer));
|
|
486
|
-
const idTokenResponse = yield jose.jwtVerify(tokens.id_token, JWKS, {
|
|
487
|
-
issuer: getIssuerVariations(this.oauthServer),
|
|
488
|
-
audience: this.clientId
|
|
489
|
-
});
|
|
490
|
-
returnPayload.idToken = idTokenResponse.payload;
|
|
491
|
-
const accessTokenResponse = yield jose.jwtVerify(
|
|
492
|
-
tokens.access_token,
|
|
493
|
-
JWKS,
|
|
494
|
-
{
|
|
495
|
-
issuer: getIssuerVariations(this.oauthServer)
|
|
496
|
-
}
|
|
497
|
-
);
|
|
498
|
-
returnPayload.accessToken = accessTokenResponse.payload;
|
|
499
|
-
if (tokens.refresh_token) {
|
|
500
|
-
const refreshResponse = yield jose.jwtVerify(tokens.refresh_token, JWKS, {
|
|
501
|
-
issuer: getIssuerVariations(this.oauthServer)
|
|
502
|
-
});
|
|
503
|
-
returnPayload.refreshToken = refreshResponse.payload;
|
|
504
|
-
}
|
|
505
|
-
return returnPayload;
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
validateExistingSession() {
|
|
509
|
-
return __async(this, null, function* () {
|
|
510
|
-
const sessionData = this.getSessionData();
|
|
511
|
-
try {
|
|
512
|
-
if (!sessionData.idToken || !sessionData.accessToken) {
|
|
513
|
-
const unAuthenticatedSession = __spreadProps(__spreadValues({}, sessionData), { authenticated: false });
|
|
514
|
-
this.updateSessionData(unAuthenticatedSession);
|
|
515
|
-
return unAuthenticatedSession;
|
|
516
|
-
}
|
|
517
|
-
yield this.validateTokens({
|
|
518
|
-
id_token: sessionData.idToken,
|
|
519
|
-
access_token: sessionData.accessToken,
|
|
520
|
-
refresh_token: sessionData.refreshToken
|
|
521
|
-
});
|
|
522
|
-
sessionData.authenticated = true;
|
|
523
|
-
return sessionData;
|
|
524
|
-
} catch (error) {
|
|
525
|
-
console.warn("Failed to validate existing tokens", error);
|
|
526
|
-
const unAuthenticatedSession = __spreadProps(__spreadValues({}, sessionData), { authenticated: false });
|
|
527
|
-
this.updateSessionData(unAuthenticatedSession);
|
|
528
|
-
return unAuthenticatedSession;
|
|
529
|
-
}
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
};
|
|
209
|
+
// src/shared/AuthProvider.tsx
|
|
210
|
+
import {
|
|
211
|
+
useCallback as useCallback2,
|
|
212
|
+
useEffect as useEffect2,
|
|
213
|
+
useMemo as useMemo2,
|
|
214
|
+
useRef as useRef2,
|
|
215
|
+
useState as useState2
|
|
216
|
+
} from "react";
|
|
217
|
+
import { useMutation as useMutation2, useQuery as useQuery2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
|
|
533
218
|
|
|
534
|
-
// src/react/components/
|
|
219
|
+
// src/react/components/CivicAuthIframeContainer.tsx
|
|
535
220
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
536
221
|
|
|
537
222
|
// src/react/components/LoadingIcon.tsx
|
|
538
|
-
import { jsx as
|
|
223
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
539
224
|
var LoadingIcon = () => /* @__PURE__ */ jsxs("div", { role: "status", children: [
|
|
540
225
|
/* @__PURE__ */ jsxs(
|
|
541
226
|
"svg",
|
|
542
227
|
{
|
|
543
228
|
"aria-hidden": "true",
|
|
544
|
-
className: "inline h-8 w-8 animate-spin fill-neutral-600 text-neutral-200 dark:fill-neutral-300 dark:text-neutral-600",
|
|
229
|
+
className: "cac-inline cac-h-8 cac-w-8 cac-animate-spin cac-fill-neutral-600 cac-text-neutral-200 dark:cac-fill-neutral-300 dark:cac-text-neutral-600",
|
|
545
230
|
viewBox: "0 0 100 101",
|
|
546
231
|
fill: "none",
|
|
547
232
|
xmlns: "http://www.w3.org/2000/svg",
|
|
548
233
|
children: [
|
|
549
|
-
/* @__PURE__ */
|
|
234
|
+
/* @__PURE__ */ jsx4(
|
|
550
235
|
"path",
|
|
551
236
|
{
|
|
552
237
|
d: "M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z",
|
|
553
238
|
fill: "currentColor"
|
|
554
239
|
}
|
|
555
240
|
),
|
|
556
|
-
/* @__PURE__ */
|
|
241
|
+
/* @__PURE__ */ jsx4(
|
|
557
242
|
"path",
|
|
558
243
|
{
|
|
559
244
|
d: "M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z",
|
|
@@ -563,11 +248,11 @@ var LoadingIcon = () => /* @__PURE__ */ jsxs("div", { role: "status", children:
|
|
|
563
248
|
]
|
|
564
249
|
}
|
|
565
250
|
),
|
|
566
|
-
/* @__PURE__ */
|
|
251
|
+
/* @__PURE__ */ jsx4("span", { className: "cac-sr-only", children: "Loading..." })
|
|
567
252
|
] });
|
|
568
253
|
|
|
569
|
-
// src/react/components/
|
|
570
|
-
import { jsx as
|
|
254
|
+
// src/react/components/CloseIcon.tsx
|
|
255
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
571
256
|
var CloseIcon = () => /* @__PURE__ */ jsxs2(
|
|
572
257
|
"svg",
|
|
573
258
|
{
|
|
@@ -582,26 +267,90 @@ var CloseIcon = () => /* @__PURE__ */ jsxs2(
|
|
|
582
267
|
strokeLinejoin: "round",
|
|
583
268
|
className: "lucide lucide-x",
|
|
584
269
|
children: [
|
|
585
|
-
/* @__PURE__ */
|
|
586
|
-
/* @__PURE__ */
|
|
270
|
+
/* @__PURE__ */ jsx5("path", { d: "M18 6 6 18" }),
|
|
271
|
+
/* @__PURE__ */ jsx5("path", { d: "m6 6 12 12" })
|
|
587
272
|
]
|
|
588
273
|
}
|
|
589
274
|
);
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
275
|
+
|
|
276
|
+
// src/react/components/CivicAuthIframe.tsx
|
|
277
|
+
import { forwardRef } from "react";
|
|
278
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
279
|
+
var CivicAuthIframe = forwardRef(
|
|
280
|
+
({ onLoad }, ref) => {
|
|
281
|
+
return /* @__PURE__ */ jsx6(
|
|
282
|
+
"iframe",
|
|
283
|
+
{
|
|
284
|
+
id: IFRAME_ID,
|
|
285
|
+
ref,
|
|
286
|
+
className: "cac-h-96 cac-w-80 cac-border-none",
|
|
287
|
+
onLoad
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
CivicAuthIframe.displayName = "CivicAuthIframe";
|
|
293
|
+
|
|
294
|
+
// src/react/components/CivicAuthIframeContainer.tsx
|
|
295
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
296
|
+
function NoChrome({
|
|
297
|
+
children
|
|
298
|
+
}) {
|
|
299
|
+
return /* @__PURE__ */ jsx7(Fragment, { children });
|
|
300
|
+
}
|
|
301
|
+
function IframeChrome({
|
|
302
|
+
children,
|
|
595
303
|
onClose
|
|
304
|
+
}) {
|
|
305
|
+
return /* @__PURE__ */ jsx7(
|
|
306
|
+
"div",
|
|
307
|
+
{
|
|
308
|
+
className: "cac-absolute cac-left-0 cac-top-0 cac-z-50 cac-flex cac-h-screen cac-w-screen cac-items-center cac-justify-center cac-bg-neutral-950 cac-bg-opacity-50",
|
|
309
|
+
onClick: onClose,
|
|
310
|
+
children: /* @__PURE__ */ jsxs3(
|
|
311
|
+
"div",
|
|
312
|
+
{
|
|
313
|
+
className: "cac-relative cac-rounded-3xl cac-bg-white cac-p-6 cac-shadow-lg",
|
|
314
|
+
onClick: (e) => e.stopPropagation(),
|
|
315
|
+
children: [
|
|
316
|
+
/* @__PURE__ */ jsx7(
|
|
317
|
+
"button",
|
|
318
|
+
{
|
|
319
|
+
className: "cac-absolute cac-right-4 cac-top-4 cac-flex cac-cursor-pointer cac-items-center cac-justify-center cac-border-none cac-bg-transparent cac-p-1 cac-text-neutral-400",
|
|
320
|
+
onClick: onClose,
|
|
321
|
+
children: /* @__PURE__ */ jsx7(CloseIcon, {})
|
|
322
|
+
}
|
|
323
|
+
),
|
|
324
|
+
children
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
var CivicAuthIframeContainer = ({
|
|
332
|
+
onClose,
|
|
333
|
+
closeOnRedirect = true
|
|
596
334
|
}) => {
|
|
597
|
-
|
|
335
|
+
var _a;
|
|
598
336
|
const [isLoading, setIsLoading] = useState(true);
|
|
337
|
+
const { isLoading: isAuthLoading } = useAuth();
|
|
338
|
+
const config = useConfig();
|
|
339
|
+
const { serverTokenExchange } = config;
|
|
340
|
+
const { setAuthResponseUrl, iframeRef } = useSession();
|
|
599
341
|
const processIframeUrl = useCallback(() => {
|
|
600
|
-
if (iframeRef.current && iframeRef.current.contentWindow) {
|
|
342
|
+
if (iframeRef && iframeRef.current && iframeRef.current.contentWindow) {
|
|
601
343
|
try {
|
|
602
344
|
const iframeUrl = iframeRef.current.contentWindow.location.href;
|
|
603
|
-
if (iframeUrl.startsWith(
|
|
604
|
-
|
|
345
|
+
if (iframeUrl.startsWith(config.redirectUrl)) {
|
|
346
|
+
if (serverTokenExchange) {
|
|
347
|
+
const params = new URL(iframeUrl).searchParams;
|
|
348
|
+
params.set("tokenExchange", "true");
|
|
349
|
+
fetch(`${config.redirectUrl}?${params.toString()}`);
|
|
350
|
+
} else {
|
|
351
|
+
setAuthResponseUrl(iframeUrl);
|
|
352
|
+
}
|
|
353
|
+
if (closeOnRedirect) onClose == null ? void 0 : onClose();
|
|
605
354
|
return true;
|
|
606
355
|
}
|
|
607
356
|
} catch (e) {
|
|
@@ -609,14 +358,24 @@ var CivicAuthIframe = ({
|
|
|
609
358
|
}
|
|
610
359
|
}
|
|
611
360
|
return false;
|
|
612
|
-
}, [
|
|
361
|
+
}, [
|
|
362
|
+
closeOnRedirect,
|
|
363
|
+
config.redirectUrl,
|
|
364
|
+
iframeRef,
|
|
365
|
+
onClose,
|
|
366
|
+
serverTokenExchange,
|
|
367
|
+
setAuthResponseUrl
|
|
368
|
+
]);
|
|
613
369
|
const intervalId = useRef();
|
|
614
|
-
|
|
615
|
-
|
|
370
|
+
const handleEscape = useCallback(
|
|
371
|
+
(event) => {
|
|
616
372
|
if (event.key === "Escape") {
|
|
617
|
-
onClose();
|
|
373
|
+
onClose == null ? void 0 : onClose();
|
|
618
374
|
}
|
|
619
|
-
}
|
|
375
|
+
},
|
|
376
|
+
[onClose]
|
|
377
|
+
);
|
|
378
|
+
useEffect(() => {
|
|
620
379
|
window.addEventListener("keydown", handleEscape);
|
|
621
380
|
return () => window.removeEventListener("keydown", handleEscape);
|
|
622
381
|
});
|
|
@@ -627,214 +386,51 @@ var CivicAuthIframe = ({
|
|
|
627
386
|
clearInterval(intervalId.current);
|
|
628
387
|
}
|
|
629
388
|
};
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
"div",
|
|
637
|
-
{
|
|
638
|
-
className: "relative rounded-3xl bg-white p-6 shadow-lg",
|
|
639
|
-
onClick: (e) => e.stopPropagation(),
|
|
640
|
-
children: [
|
|
641
|
-
/* @__PURE__ */ jsx4(
|
|
642
|
-
"button",
|
|
643
|
-
{
|
|
644
|
-
className: "absolute right-4 top-4 flex cursor-pointer items-center justify-center border-none bg-transparent p-1 text-neutral-400",
|
|
645
|
-
onClick: onClose,
|
|
646
|
-
children: /* @__PURE__ */ jsx4(CloseIcon, {})
|
|
647
|
-
}
|
|
648
|
-
),
|
|
649
|
-
isLoading && /* @__PURE__ */ jsx4("div", { className: "absolute inset-0 flex items-center justify-center rounded-3xl bg-neutral-100", children: /* @__PURE__ */ jsx4(LoadingIcon, {}) }),
|
|
650
|
-
/* @__PURE__ */ jsx4(
|
|
651
|
-
"iframe",
|
|
652
|
-
{
|
|
653
|
-
id: IFRAME_ID,
|
|
654
|
-
ref: iframeRef,
|
|
655
|
-
src: authUrl,
|
|
656
|
-
className: "h-48 w-80 border-none",
|
|
657
|
-
onLoad: handleIframeLoad
|
|
658
|
-
}
|
|
659
|
-
)
|
|
660
|
-
]
|
|
661
|
-
}
|
|
662
|
-
)
|
|
663
|
-
}
|
|
664
|
-
);
|
|
389
|
+
const showLoadingIcon = isLoading || isAuthLoading || !((_a = iframeRef == null ? void 0 : iframeRef.current) == null ? void 0 : _a.getAttribute("src"));
|
|
390
|
+
const WrapperComponent = config.modalIframe ? IframeChrome : NoChrome;
|
|
391
|
+
return /* @__PURE__ */ jsxs3(WrapperComponent, { onClose, children: [
|
|
392
|
+
showLoadingIcon && /* @__PURE__ */ jsx7("div", { className: "cac-absolute cac-inset-0 cac-flex cac-items-center cac-justify-center cac-rounded-3xl cac-bg-neutral-100", children: /* @__PURE__ */ jsx7(LoadingIcon, {}) }),
|
|
393
|
+
/* @__PURE__ */ jsx7(CivicAuthIframe, { ref: iframeRef, onLoad: handleIframeLoad })
|
|
394
|
+
] });
|
|
665
395
|
};
|
|
666
396
|
|
|
667
|
-
// src/react/components/UserButton.tsx
|
|
668
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
669
|
-
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
670
|
-
var ChevronDown = () => /* @__PURE__ */ jsx5(
|
|
671
|
-
"svg",
|
|
672
|
-
{
|
|
673
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
674
|
-
width: "24",
|
|
675
|
-
height: "24",
|
|
676
|
-
viewBox: "0 0 24 24",
|
|
677
|
-
fill: "none",
|
|
678
|
-
stroke: "currentColor",
|
|
679
|
-
strokeWidth: "2",
|
|
680
|
-
strokeLinecap: "round",
|
|
681
|
-
strokeLinejoin: "round",
|
|
682
|
-
className: "lucide lucide-chevron-down",
|
|
683
|
-
children: /* @__PURE__ */ jsx5("path", { d: "m6 9 6 6 6-6" })
|
|
684
|
-
}
|
|
685
|
-
);
|
|
686
|
-
var ChevronUp = () => /* @__PURE__ */ jsx5(
|
|
687
|
-
"svg",
|
|
688
|
-
{
|
|
689
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
690
|
-
width: "24",
|
|
691
|
-
height: "24",
|
|
692
|
-
viewBox: "0 0 24 24",
|
|
693
|
-
fill: "none",
|
|
694
|
-
stroke: "currentColor",
|
|
695
|
-
strokeWidth: "2",
|
|
696
|
-
strokeLinecap: "round",
|
|
697
|
-
strokeLinejoin: "round",
|
|
698
|
-
className: "lucide lucide-chevron-up",
|
|
699
|
-
children: /* @__PURE__ */ jsx5("path", { d: "m18 15-6-6-6 6" })
|
|
700
|
-
}
|
|
701
|
-
);
|
|
702
|
-
var UserButton = ({
|
|
703
|
-
displayMode,
|
|
704
|
-
className
|
|
705
|
-
}) => {
|
|
706
|
-
const [isOpen, setIsOpen] = useState2(false);
|
|
707
|
-
const { signIn, isAuthenticated, signOut } = useAuth();
|
|
708
|
-
const { user } = useUser();
|
|
709
|
-
useEffect2(() => {
|
|
710
|
-
const handleEscape = (event) => {
|
|
711
|
-
if (event.key === "Escape") {
|
|
712
|
-
setIsOpen(false);
|
|
713
|
-
}
|
|
714
|
-
};
|
|
715
|
-
if (isOpen) {
|
|
716
|
-
window.addEventListener("keydown", handleEscape);
|
|
717
|
-
}
|
|
718
|
-
return () => {
|
|
719
|
-
window.removeEventListener("keydown", handleEscape);
|
|
720
|
-
};
|
|
721
|
-
}, [isOpen]);
|
|
722
|
-
useEffect2(() => {
|
|
723
|
-
const handleClick = (event) => {
|
|
724
|
-
const target = event.target;
|
|
725
|
-
if (!target.closest("#civic-dropdown-container")) {
|
|
726
|
-
setIsOpen(false);
|
|
727
|
-
}
|
|
728
|
-
};
|
|
729
|
-
if (isOpen) {
|
|
730
|
-
window.addEventListener("click", handleClick);
|
|
731
|
-
}
|
|
732
|
-
return () => {
|
|
733
|
-
window.removeEventListener("click", handleClick);
|
|
734
|
-
};
|
|
735
|
-
}, [isOpen]);
|
|
736
|
-
useEffect2(() => {
|
|
737
|
-
if (!isAuthenticated) {
|
|
738
|
-
setIsOpen(false);
|
|
739
|
-
}
|
|
740
|
-
}, [isAuthenticated]);
|
|
741
|
-
if (isAuthenticated) {
|
|
742
|
-
return /* @__PURE__ */ jsxs3("div", { className: "relative", id: "civic-dropdown-container", children: [
|
|
743
|
-
/* @__PURE__ */ jsxs3(
|
|
744
|
-
"button",
|
|
745
|
-
{
|
|
746
|
-
className: cn(
|
|
747
|
-
"flex w-full items-center justify-between gap-2 rounded-full border border-neutral-500 px-3 py-2 text-neutral-500 transition-colors hover:bg-neutral-200 hover:bg-opacity-50",
|
|
748
|
-
className
|
|
749
|
-
),
|
|
750
|
-
onClick: () => setIsOpen((isOpen2) => !isOpen2),
|
|
751
|
-
children: [
|
|
752
|
-
(user == null ? void 0 : user.picture) ? /* @__PURE__ */ jsx5("span", { className: "relative flex h-10 w-10 shrink-0 gap-2 overflow-hidden rounded-full", children: /* @__PURE__ */ jsx5(
|
|
753
|
-
"img",
|
|
754
|
-
{
|
|
755
|
-
className: "h-full w-full object-cover",
|
|
756
|
-
src: user.picture,
|
|
757
|
-
alt: (user == null ? void 0 : user.name) || (user == null ? void 0 : user.email)
|
|
758
|
-
}
|
|
759
|
-
) }) : /* @__PURE__ */ jsx5("div", {}),
|
|
760
|
-
/* @__PURE__ */ jsx5("span", { children: (user == null ? void 0 : user.name) || (user == null ? void 0 : user.email) }),
|
|
761
|
-
isOpen ? /* @__PURE__ */ jsx5(ChevronUp, {}) : /* @__PURE__ */ jsx5(ChevronDown, {})
|
|
762
|
-
]
|
|
763
|
-
}
|
|
764
|
-
),
|
|
765
|
-
/* @__PURE__ */ jsx5(
|
|
766
|
-
"div",
|
|
767
|
-
{
|
|
768
|
-
className: isOpen ? "absolute right-0 mt-2 w-full rounded-lg bg-white py-2 text-neutral-500 shadow-xl" : "hidden",
|
|
769
|
-
children: /* @__PURE__ */ jsx5("ul", { children: /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsx5(
|
|
770
|
-
"button",
|
|
771
|
-
{
|
|
772
|
-
className: "block w-full px-4 py-2 transition-colors hover:bg-neutral-200 hover:bg-opacity-50",
|
|
773
|
-
onClick: () => signOut(),
|
|
774
|
-
children: "Logout"
|
|
775
|
-
}
|
|
776
|
-
) }) })
|
|
777
|
-
}
|
|
778
|
-
)
|
|
779
|
-
] });
|
|
780
|
-
}
|
|
781
|
-
return /* @__PURE__ */ jsx5(
|
|
782
|
-
"button",
|
|
783
|
-
{
|
|
784
|
-
className: cn(
|
|
785
|
-
"rounded-full border border-neutral-500 px-3 py-2 transition-colors hover:bg-neutral-200 hover:bg-opacity-50",
|
|
786
|
-
className
|
|
787
|
-
),
|
|
788
|
-
onClick: () => signIn(displayMode),
|
|
789
|
-
children: "Sign in"
|
|
790
|
-
}
|
|
791
|
-
);
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
// src/react/providers/ParamsProvider.tsx
|
|
795
|
-
import { createContext as createContext3 } from "react";
|
|
796
|
-
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
797
|
-
var ParamsContext = createContext3(null);
|
|
798
|
-
var ParamsProvider = ({
|
|
799
|
-
children,
|
|
800
|
-
clientId,
|
|
801
|
-
redirectUrl,
|
|
802
|
-
config,
|
|
803
|
-
nonce
|
|
804
|
-
}) => {
|
|
805
|
-
const value = {
|
|
806
|
-
clientId,
|
|
807
|
-
redirectUrl,
|
|
808
|
-
config,
|
|
809
|
-
nonce
|
|
810
|
-
};
|
|
811
|
-
return /* @__PURE__ */ jsx6(ParamsContext.Provider, { value, children });
|
|
812
|
-
};
|
|
813
|
-
|
|
814
|
-
// src/react/providers/SessionProvider.tsx
|
|
815
|
-
import { createContext as createContext4 } from "react";
|
|
816
|
-
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
817
|
-
var defaultSession = {
|
|
818
|
-
authenticated: false,
|
|
819
|
-
idToken: void 0,
|
|
820
|
-
accessToken: void 0,
|
|
821
|
-
displayMode: "iframe"
|
|
822
|
-
};
|
|
823
|
-
var SessionContext = createContext4(defaultSession);
|
|
824
|
-
var SessionProvider = ({ children, session }) => /* @__PURE__ */ jsx7(SessionContext.Provider, { value: session || defaultSession, children });
|
|
825
|
-
|
|
826
|
-
// src/constants.ts
|
|
827
|
-
var DEFAULT_SCOPES = ["openid", "profile", "email", "forwardedTokens"];
|
|
828
|
-
|
|
829
397
|
// src/config.ts
|
|
830
398
|
var authConfig = {
|
|
831
399
|
// TODO change this to the production URL once we're out of beta
|
|
832
400
|
oauthServer: "https://auth-dev.civic.com/oauth/"
|
|
833
401
|
};
|
|
834
402
|
|
|
835
|
-
// src/react/providers/
|
|
836
|
-
import {
|
|
837
|
-
|
|
403
|
+
// src/react/providers/ConfigProvider.tsx
|
|
404
|
+
import { createContext as createContext5 } from "react";
|
|
405
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
406
|
+
var defaultConfig = {
|
|
407
|
+
config: authConfig,
|
|
408
|
+
redirectUrl: "",
|
|
409
|
+
modalIframe: true,
|
|
410
|
+
serverTokenExchange: false
|
|
411
|
+
};
|
|
412
|
+
var ConfigContext = createContext5(defaultConfig);
|
|
413
|
+
var ConfigProvider = ({
|
|
414
|
+
children,
|
|
415
|
+
config,
|
|
416
|
+
redirectUrl,
|
|
417
|
+
modalIframe,
|
|
418
|
+
serverTokenExchange
|
|
419
|
+
}) => /* @__PURE__ */ jsx8(
|
|
420
|
+
ConfigContext.Provider,
|
|
421
|
+
{
|
|
422
|
+
value: {
|
|
423
|
+
config,
|
|
424
|
+
redirectUrl,
|
|
425
|
+
modalIframe: !!modalIframe,
|
|
426
|
+
serverTokenExchange
|
|
427
|
+
},
|
|
428
|
+
children
|
|
429
|
+
}
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
// src/shared/AuthProvider.tsx
|
|
433
|
+
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
838
434
|
var globalThisObject;
|
|
839
435
|
if (typeof window !== "undefined") {
|
|
840
436
|
globalThisObject = window;
|
|
@@ -844,35 +440,36 @@ if (typeof window !== "undefined") {
|
|
|
844
440
|
globalThisObject = Function("return this")();
|
|
845
441
|
}
|
|
846
442
|
globalThisObject.globalThis = globalThisObject;
|
|
443
|
+
function BlockDisplay({ children }) {
|
|
444
|
+
return /* @__PURE__ */ jsx9("div", { className: "cac-absolute cac-left-0 cac-top-0 cac-z-50 cac-flex cac-h-screen cac-w-screen cac-items-center cac-justify-center cac-bg-white", children: /* @__PURE__ */ jsx9("div", { className: "cac-absolute cac-inset-0 cac-flex cac-items-center cac-justify-center cac-bg-white", children }) });
|
|
445
|
+
}
|
|
847
446
|
var AuthProvider = ({
|
|
848
447
|
children,
|
|
849
448
|
clientId,
|
|
850
449
|
redirectUrl: inputRedirectUrl,
|
|
851
450
|
config = authConfig,
|
|
852
|
-
nonce,
|
|
853
451
|
onSignIn,
|
|
854
|
-
onSignOut
|
|
452
|
+
onSignOut,
|
|
453
|
+
pkceConsumer,
|
|
454
|
+
nonce,
|
|
455
|
+
modalIframe = true
|
|
855
456
|
}) => {
|
|
856
|
-
const [iframeUrl, setIframeUrl] =
|
|
857
|
-
const [currentUrl, setCurrentUrl] =
|
|
858
|
-
const [isInIframe, setIsInIframe] =
|
|
859
|
-
const [authResponseUrl, setAuthResponseUrl] =
|
|
860
|
-
const [
|
|
861
|
-
const [
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
457
|
+
const [iframeUrl, setIframeUrl] = useState2(null);
|
|
458
|
+
const [currentUrl, setCurrentUrl] = useState2(null);
|
|
459
|
+
const [isInIframe, setIsInIframe] = useState2(false);
|
|
460
|
+
const [authResponseUrl, setAuthResponseUrl] = useState2(null);
|
|
461
|
+
const [tokenExchangeError, setTokenExchangeError] = useState2();
|
|
462
|
+
const [displayMode, setDisplayMode] = useState2("iframe");
|
|
463
|
+
const [browserAuthenticationInitiator, setBrowserAuthenticationInitiator] = useState2();
|
|
464
|
+
const [showIFrame, setShowIFrame] = useState2(false);
|
|
465
|
+
const [isRedirecting, setIsRedirecting] = useState2(false);
|
|
466
|
+
const queryClient3 = useQueryClient2();
|
|
467
|
+
const iframeRef = useRef2(null);
|
|
468
|
+
const serverTokenExchange = pkceConsumer instanceof ConfidentialClientPKCEConsumer;
|
|
469
|
+
useEffect2(() => {
|
|
865
470
|
if (typeof globalThis.window !== "undefined") {
|
|
866
471
|
setCurrentUrl(globalThis.window.location.href);
|
|
867
|
-
|
|
868
|
-
try {
|
|
869
|
-
if (((_b = (_a = globalThis.window) == null ? void 0 : _a.frameElement) == null ? void 0 : _b.id) === "civic-auth-iframe") {
|
|
870
|
-
isInIframeVal = true;
|
|
871
|
-
}
|
|
872
|
-
} catch (_e) {
|
|
873
|
-
isInIframeVal = false;
|
|
874
|
-
}
|
|
875
|
-
console.log("isInIframeVal", isInIframeVal);
|
|
472
|
+
const isInIframeVal = isWindowInIframe(globalThis.window);
|
|
876
473
|
setIsInIframe(isInIframeVal);
|
|
877
474
|
}
|
|
878
475
|
}, []);
|
|
@@ -880,42 +477,56 @@ var AuthProvider = ({
|
|
|
880
477
|
() => (inputRedirectUrl || currentUrl || "").split("?")[0],
|
|
881
478
|
[currentUrl, inputRedirectUrl]
|
|
882
479
|
);
|
|
883
|
-
const authService =
|
|
884
|
-
|
|
480
|
+
const [authService, setAuthService] = useState2();
|
|
481
|
+
useEffect2(() => {
|
|
482
|
+
if (!currentUrl) return;
|
|
483
|
+
BrowserAuthenticationService.build({
|
|
885
484
|
clientId,
|
|
886
485
|
redirectUrl,
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
);
|
|
486
|
+
oauthServer: config.oauthServer,
|
|
487
|
+
scopes: DEFAULT_SCOPES,
|
|
488
|
+
displayMode
|
|
489
|
+
}).then(setAuthService);
|
|
490
|
+
}, [currentUrl, clientId, redirectUrl, config, displayMode]);
|
|
892
491
|
const {
|
|
893
492
|
data: session,
|
|
894
493
|
isLoading,
|
|
895
494
|
error
|
|
896
495
|
} = useQuery2({
|
|
897
|
-
queryKey: [
|
|
496
|
+
queryKey: [
|
|
497
|
+
"session",
|
|
498
|
+
authResponseUrl,
|
|
499
|
+
iframeUrl,
|
|
500
|
+
currentUrl,
|
|
501
|
+
isInIframe,
|
|
502
|
+
authService
|
|
503
|
+
],
|
|
898
504
|
queryFn: () => __async(void 0, null, function* () {
|
|
899
|
-
const url = new URL(globalThis.window.location.href || "");
|
|
900
|
-
console.log("AuthProvider useQuery", { isInIframe, url, authService });
|
|
901
505
|
if (!authService) {
|
|
902
506
|
return { authenticated: false };
|
|
903
507
|
}
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
}
|
|
508
|
+
const url = new URL(
|
|
509
|
+
authResponseUrl ? authResponseUrl : globalThis.window.location.href || ""
|
|
510
|
+
);
|
|
908
511
|
const code = url.searchParams.get("code");
|
|
909
|
-
|
|
512
|
+
const state = url.searchParams.get("state");
|
|
513
|
+
if (!serverTokenExchange && code && state && !isInIframe) {
|
|
910
514
|
try {
|
|
911
|
-
console.log("AuthProvider useQuery code", {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
);
|
|
916
|
-
|
|
515
|
+
console.log("AuthProvider useQuery code", {
|
|
516
|
+
isInIframe,
|
|
517
|
+
code,
|
|
518
|
+
state
|
|
519
|
+
});
|
|
520
|
+
yield authService.tokenExchange(code, state);
|
|
521
|
+
const clientStorage = new LocalStorageAdapter();
|
|
522
|
+
const user = yield getUser(clientStorage);
|
|
523
|
+
if (!user) {
|
|
524
|
+
throw new Error("Failed to get user info");
|
|
525
|
+
}
|
|
526
|
+
const userSession = new GenericUserSession(clientStorage);
|
|
527
|
+
userSession.set(user);
|
|
917
528
|
onSignIn == null ? void 0 : onSignIn();
|
|
918
|
-
return
|
|
529
|
+
return authService.getSessionData();
|
|
919
530
|
} catch (error2) {
|
|
920
531
|
setTokenExchangeError(error2);
|
|
921
532
|
onSignIn == null ? void 0 : onSignIn(
|
|
@@ -924,173 +535,460 @@ var AuthProvider = ({
|
|
|
924
535
|
return { authenticated: false };
|
|
925
536
|
}
|
|
926
537
|
}
|
|
538
|
+
const existingSessionData = yield authService.validateExistingSession();
|
|
539
|
+
if (existingSessionData.authenticated) {
|
|
540
|
+
return existingSessionData;
|
|
541
|
+
}
|
|
927
542
|
return existingSessionData;
|
|
928
|
-
})
|
|
929
|
-
enabled: !!authService && !!currentUrl && !isInIframe
|
|
543
|
+
})
|
|
930
544
|
});
|
|
931
545
|
const signOutMutation = useMutation2({
|
|
932
546
|
mutationFn: () => __async(void 0, null, function* () {
|
|
933
|
-
|
|
547
|
+
const authInitiator = getAuthInitiator();
|
|
548
|
+
authInitiator == null ? void 0 : authInitiator.signOut();
|
|
549
|
+
setIframeUrl(null);
|
|
550
|
+
setShowIFrame(false);
|
|
934
551
|
setAuthResponseUrl(null);
|
|
935
552
|
onSignOut == null ? void 0 : onSignOut();
|
|
936
553
|
}),
|
|
937
554
|
onSuccess: () => {
|
|
938
|
-
|
|
555
|
+
queryClient3.setQueryData(
|
|
556
|
+
[
|
|
557
|
+
"session",
|
|
558
|
+
authResponseUrl,
|
|
559
|
+
iframeUrl,
|
|
560
|
+
currentUrl,
|
|
561
|
+
isInIframe,
|
|
562
|
+
authService
|
|
563
|
+
],
|
|
564
|
+
null
|
|
565
|
+
);
|
|
939
566
|
}
|
|
940
567
|
});
|
|
568
|
+
const getAuthInitiator = useCallback2(
|
|
569
|
+
(overrideDisplayMode) => {
|
|
570
|
+
const useDisplayMode = overrideDisplayMode || displayMode;
|
|
571
|
+
if (!pkceConsumer) {
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
return browserAuthenticationInitiator || new BrowserAuthenticationInitiator({
|
|
575
|
+
pkceConsumer,
|
|
576
|
+
// generate and retrieve the challenge client-side
|
|
577
|
+
clientId,
|
|
578
|
+
redirectUrl,
|
|
579
|
+
state: generateState(useDisplayMode),
|
|
580
|
+
scopes: DEFAULT_SCOPES,
|
|
581
|
+
displayMode: useDisplayMode,
|
|
582
|
+
oauthServer: config.oauthServer,
|
|
583
|
+
// the endpoints to use for the login (if not obtained from the auth server
|
|
584
|
+
endpointOverrides: config.endpoints,
|
|
585
|
+
nonce
|
|
586
|
+
});
|
|
587
|
+
},
|
|
588
|
+
[
|
|
589
|
+
displayMode,
|
|
590
|
+
browserAuthenticationInitiator,
|
|
591
|
+
clientId,
|
|
592
|
+
redirectUrl,
|
|
593
|
+
config.oauthServer,
|
|
594
|
+
config.endpoints,
|
|
595
|
+
pkceConsumer,
|
|
596
|
+
nonce
|
|
597
|
+
]
|
|
598
|
+
);
|
|
941
599
|
const signIn = useCallback2(
|
|
942
600
|
(overrideDisplayMode = "iframe") => __async(void 0, null, function* () {
|
|
943
|
-
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
DEFAULT_SCOPES,
|
|
947
|
-
overrideDisplayMode,
|
|
948
|
-
nonce
|
|
949
|
-
);
|
|
601
|
+
setDisplayMode(overrideDisplayMode);
|
|
602
|
+
const authInitiator = getAuthInitiator(overrideDisplayMode);
|
|
603
|
+
setBrowserAuthenticationInitiator(authInitiator);
|
|
950
604
|
if (overrideDisplayMode === "iframe") {
|
|
951
|
-
|
|
952
|
-
|
|
605
|
+
setShowIFrame(true);
|
|
606
|
+
} else if (overrideDisplayMode === "redirect") {
|
|
607
|
+
setIsRedirecting(true);
|
|
953
608
|
}
|
|
954
|
-
|
|
609
|
+
authInitiator == null ? void 0 : authInitiator.signIn(iframeRef.current);
|
|
955
610
|
}),
|
|
956
|
-
[
|
|
611
|
+
[getAuthInitiator]
|
|
957
612
|
);
|
|
958
613
|
const isAuthenticated = useMemo2(
|
|
959
614
|
() => session ? session.authenticated : false,
|
|
960
615
|
[session]
|
|
961
616
|
);
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
});
|
|
972
|
-
if (code && !isAuthenticated && !tokenExchangeInProgress && !isInIframe) {
|
|
973
|
-
try {
|
|
974
|
-
setTokenExchangeInProgress(true);
|
|
975
|
-
authService.tokenExchange(authResponseUrl).then((newSession) => {
|
|
976
|
-
queryClient2.setQueryData(["session"], newSession);
|
|
977
|
-
setIframeUrl(null);
|
|
978
|
-
onSignIn == null ? void 0 : onSignIn();
|
|
979
|
-
}).catch((error2) => {
|
|
980
|
-
setTokenExchangeError(error2);
|
|
981
|
-
}).finally(() => {
|
|
982
|
-
setTokenExchangeInProgress(false);
|
|
983
|
-
});
|
|
984
|
-
} catch (error2) {
|
|
985
|
-
setTokenExchangeInProgress(false);
|
|
986
|
-
onSignIn == null ? void 0 : onSignIn(
|
|
987
|
-
error2 instanceof Error ? error2 : new Error("Failed to sign in")
|
|
988
|
-
);
|
|
617
|
+
const {
|
|
618
|
+
data: autoSignIn,
|
|
619
|
+
isLoading: autoSignInLoading,
|
|
620
|
+
error: autoSignInError
|
|
621
|
+
} = useQuery2({
|
|
622
|
+
queryKey: ["autoSignIn", modalIframe, redirectUrl, isAuthenticated],
|
|
623
|
+
queryFn: () => __async(void 0, null, function* () {
|
|
624
|
+
if (!modalIframe && redirectUrl && !isAuthenticated && iframeRef.current) {
|
|
625
|
+
signIn("iframe");
|
|
989
626
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
queryClient2,
|
|
995
|
-
isAuthenticated,
|
|
996
|
-
authResponseUrl,
|
|
997
|
-
tokenExchangeInProgress,
|
|
998
|
-
isInIframe
|
|
999
|
-
]);
|
|
627
|
+
return true;
|
|
628
|
+
}),
|
|
629
|
+
refetchOnWindowFocus: false
|
|
630
|
+
});
|
|
1000
631
|
const value = useMemo2(
|
|
1001
632
|
() => ({
|
|
1002
633
|
isLoading,
|
|
1003
634
|
error,
|
|
1004
|
-
signOut:
|
|
635
|
+
signOut: () => __async(void 0, null, function* () {
|
|
636
|
+
yield signOutMutation.mutateAsync();
|
|
637
|
+
}),
|
|
1005
638
|
isAuthenticated,
|
|
1006
639
|
signIn
|
|
1007
640
|
}),
|
|
1008
|
-
[isLoading, error, signOutMutation
|
|
641
|
+
[isLoading, error, signOutMutation, isAuthenticated, signIn]
|
|
1009
642
|
);
|
|
1010
|
-
return /* @__PURE__ */
|
|
1011
|
-
|
|
643
|
+
return /* @__PURE__ */ jsx9(AuthContext.Provider, { value, children: /* @__PURE__ */ jsx9(
|
|
644
|
+
ConfigProvider,
|
|
1012
645
|
{
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
ParamsProvider,
|
|
646
|
+
config,
|
|
647
|
+
redirectUrl,
|
|
648
|
+
modalIframe,
|
|
649
|
+
serverTokenExchange,
|
|
650
|
+
children: /* @__PURE__ */ jsx9(
|
|
651
|
+
SessionProvider,
|
|
1020
652
|
{
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
CivicAuthIframe,
|
|
653
|
+
session,
|
|
654
|
+
setAuthResponseUrl,
|
|
655
|
+
iframeRef,
|
|
656
|
+
children: /* @__PURE__ */ jsx9(TokenProvider, { children: /* @__PURE__ */ jsxs4(UserProvider, { storage: new LocalStorageAdapter(), children: [
|
|
657
|
+
modalIframe && !isInIframe && !(session == null ? void 0 : session.authenticated) && /* @__PURE__ */ jsx9(
|
|
658
|
+
"div",
|
|
1028
659
|
{
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
660
|
+
style: showIFrame ? { display: "block" } : { display: "none" },
|
|
661
|
+
children: /* @__PURE__ */ jsx9(
|
|
662
|
+
CivicAuthIframeContainer,
|
|
663
|
+
{
|
|
664
|
+
onClose: () => setShowIFrame(false)
|
|
665
|
+
}
|
|
666
|
+
)
|
|
1033
667
|
}
|
|
1034
668
|
),
|
|
1035
|
-
(
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
] }) : /* @__PURE__ */ jsx8(LoadingIcon, {}) })
|
|
1041
|
-
] }),
|
|
669
|
+
modalIframe && (isInIframe || isRedirecting || isLoading) && /* @__PURE__ */ jsx9(BlockDisplay, { children: /* @__PURE__ */ jsx9(LoadingIcon, {}) }),
|
|
670
|
+
(tokenExchangeError || error) && /* @__PURE__ */ jsx9(BlockDisplay, { children: /* @__PURE__ */ jsxs4("div", { children: [
|
|
671
|
+
"Error: ",
|
|
672
|
+
(tokenExchangeError || error).message
|
|
673
|
+
] }) }),
|
|
1042
674
|
children
|
|
1043
|
-
] }) })
|
|
675
|
+
] }) })
|
|
1044
676
|
}
|
|
1045
677
|
)
|
|
1046
678
|
}
|
|
1047
|
-
);
|
|
679
|
+
) });
|
|
1048
680
|
};
|
|
1049
681
|
|
|
1050
|
-
// src/
|
|
682
|
+
// src/shared/CivicAuthProvider.tsx
|
|
1051
683
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
1052
|
-
import
|
|
684
|
+
import "@civic/auth/styles.css";
|
|
685
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1053
686
|
var queryClient = new QueryClient();
|
|
1054
|
-
var
|
|
687
|
+
var CivicAuthProvider = (_a) => {
|
|
1055
688
|
var _b = _a, { children } = _b, props = __objRest(_b, ["children"]);
|
|
1056
|
-
return /* @__PURE__ */
|
|
689
|
+
return /* @__PURE__ */ jsx10(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx10(
|
|
690
|
+
AuthProvider,
|
|
691
|
+
__spreadProps(__spreadValues({}, props), {
|
|
692
|
+
pkceConsumer: new BrowserPublicClientPKCEProducer(),
|
|
693
|
+
children
|
|
694
|
+
})
|
|
695
|
+
) });
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
// src/react/providers/NextAuthProvider.tsx
|
|
699
|
+
import { createContext as createContext6, useContext as useContext4, useEffect as useEffect4, useState as useState3 } from "react";
|
|
700
|
+
|
|
701
|
+
// src/react/hooks/useUserCookie.ts
|
|
702
|
+
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
703
|
+
import { useRouter } from "next/navigation.js";
|
|
704
|
+
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
705
|
+
|
|
706
|
+
// src/lib/cookies.ts
|
|
707
|
+
var getCookieValue = (key, window2) => {
|
|
708
|
+
const cookie = window2.document.cookie;
|
|
709
|
+
if (!cookie) return null;
|
|
710
|
+
const cookies = cookie.split(";");
|
|
711
|
+
for (const c of cookies) {
|
|
712
|
+
const [name, value] = c.trim().split("=");
|
|
713
|
+
if (value && name === key) {
|
|
714
|
+
try {
|
|
715
|
+
return JSON.parse(decodeURIComponent(value));
|
|
716
|
+
} catch (e) {
|
|
717
|
+
console.log("Error parsing cookie value", e);
|
|
718
|
+
return value;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return null;
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
// src/react/hooks/useUserCookie.ts
|
|
726
|
+
var getUserFromCookie = () => {
|
|
727
|
+
const userCookie = getCookieValue("user", globalThis.window);
|
|
728
|
+
return userCookie;
|
|
729
|
+
};
|
|
730
|
+
var useUserCookie = () => {
|
|
731
|
+
const hasRunRef = useRef3(false);
|
|
732
|
+
const router = useRouter();
|
|
733
|
+
const { data: user } = useQuery3({
|
|
734
|
+
queryKey: ["user"],
|
|
735
|
+
queryFn: () => getUserFromCookie(),
|
|
736
|
+
refetchInterval: 2e3,
|
|
737
|
+
refetchIntervalInBackground: true,
|
|
738
|
+
enabled: !hasRunRef.current,
|
|
739
|
+
refetchOnWindowFocus: true
|
|
740
|
+
});
|
|
741
|
+
useEffect3(() => {
|
|
742
|
+
if (user) {
|
|
743
|
+
if (!hasRunRef.current) {
|
|
744
|
+
hasRunRef.current = true;
|
|
745
|
+
router.refresh();
|
|
746
|
+
}
|
|
747
|
+
} else {
|
|
748
|
+
hasRunRef.current = false;
|
|
749
|
+
}
|
|
750
|
+
}, [user, router]);
|
|
751
|
+
return user;
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
// src/react/providers/NextAuthProvider.tsx
|
|
755
|
+
import { QueryClient as QueryClient2, QueryClientProvider as QueryClientProvider2 } from "@tanstack/react-query";
|
|
756
|
+
import "@civic/auth/styles.css";
|
|
757
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
758
|
+
var queryClient2 = new QueryClient2();
|
|
759
|
+
var defaultUserContext = { user: null };
|
|
760
|
+
var UserContext2 = createContext6(defaultUserContext);
|
|
761
|
+
var CivicNextAuthProvider = (_a) => {
|
|
762
|
+
var _b = _a, {
|
|
763
|
+
children
|
|
764
|
+
} = _b, props = __objRest(_b, [
|
|
765
|
+
"children"
|
|
766
|
+
]);
|
|
767
|
+
const user = useUserCookie();
|
|
768
|
+
const [redirectUrl, setRedirectUrl] = useState3("");
|
|
769
|
+
const { clientId, oauthServer, callbackUrl, challengeUrl } = resolveAuthConfig();
|
|
770
|
+
useEffect4(() => {
|
|
771
|
+
if (typeof globalThis.window !== "undefined") {
|
|
772
|
+
const currentUrl = globalThis.window.location.href;
|
|
773
|
+
setRedirectUrl(resolveCallbackUrl(resolveAuthConfig(), currentUrl));
|
|
774
|
+
}
|
|
775
|
+
}, [callbackUrl]);
|
|
776
|
+
return /* @__PURE__ */ jsx11(QueryClientProvider2, { client: queryClient2, children: /* @__PURE__ */ jsx11(
|
|
777
|
+
AuthProvider,
|
|
778
|
+
__spreadProps(__spreadValues({}, props), {
|
|
779
|
+
redirectUrl,
|
|
780
|
+
config: { oauthServer },
|
|
781
|
+
clientId,
|
|
782
|
+
pkceConsumer: new ConfidentialClientPKCEConsumer(challengeUrl),
|
|
783
|
+
children: /* @__PURE__ */ jsx11(UserContext2.Provider, { value: user, children })
|
|
784
|
+
})
|
|
785
|
+
) });
|
|
1057
786
|
};
|
|
787
|
+
var useNextUser = () => useContext4(UserContext2);
|
|
1058
788
|
|
|
1059
789
|
// src/react/hooks/useUser.tsx
|
|
1060
790
|
var useUser = () => {
|
|
1061
|
-
const context =
|
|
791
|
+
const context = useContext5(UserContext);
|
|
1062
792
|
if (!context) {
|
|
1063
793
|
throw new Error("useUser must be used within a UserProvider");
|
|
1064
794
|
}
|
|
1065
795
|
return context;
|
|
1066
796
|
};
|
|
1067
797
|
|
|
1068
|
-
// src/react/hooks/
|
|
1069
|
-
import { useContext as
|
|
1070
|
-
var
|
|
1071
|
-
const context =
|
|
798
|
+
// src/react/hooks/useConfig.tsx
|
|
799
|
+
import { useContext as useContext6 } from "react";
|
|
800
|
+
var useConfig = () => {
|
|
801
|
+
const context = useContext6(ConfigContext);
|
|
1072
802
|
if (!context) {
|
|
1073
|
-
throw new Error("
|
|
803
|
+
throw new Error("useConfig must be used within an ConfigProvider");
|
|
1074
804
|
}
|
|
1075
805
|
return context;
|
|
1076
806
|
};
|
|
1077
807
|
|
|
1078
|
-
// src/react/
|
|
1079
|
-
import {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
808
|
+
// src/react/components/UserButton.tsx
|
|
809
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useState as useState4 } from "react";
|
|
810
|
+
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
811
|
+
var ChevronDown = () => /* @__PURE__ */ jsx12(
|
|
812
|
+
"svg",
|
|
813
|
+
{
|
|
814
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
815
|
+
width: "24",
|
|
816
|
+
height: "24",
|
|
817
|
+
viewBox: "0 0 24 24",
|
|
818
|
+
fill: "none",
|
|
819
|
+
stroke: "currentColor",
|
|
820
|
+
strokeWidth: "2",
|
|
821
|
+
strokeLinecap: "round",
|
|
822
|
+
strokeLinejoin: "round",
|
|
823
|
+
className: "lucide lucide-chevron-down",
|
|
824
|
+
children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" })
|
|
1084
825
|
}
|
|
1085
|
-
|
|
826
|
+
);
|
|
827
|
+
var ChevronUp = () => /* @__PURE__ */ jsx12(
|
|
828
|
+
"svg",
|
|
829
|
+
{
|
|
830
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
831
|
+
width: "24",
|
|
832
|
+
height: "24",
|
|
833
|
+
viewBox: "0 0 24 24",
|
|
834
|
+
fill: "none",
|
|
835
|
+
stroke: "currentColor",
|
|
836
|
+
strokeWidth: "2",
|
|
837
|
+
strokeLinecap: "round",
|
|
838
|
+
strokeLinejoin: "round",
|
|
839
|
+
className: "lucide lucide-chevron-up",
|
|
840
|
+
children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" })
|
|
841
|
+
}
|
|
842
|
+
);
|
|
843
|
+
var UserButton = ({
|
|
844
|
+
displayMode,
|
|
845
|
+
className
|
|
846
|
+
}) => {
|
|
847
|
+
const [isOpen, setIsOpen] = useState4(false);
|
|
848
|
+
const { signIn, isAuthenticated, signOut } = useAuth();
|
|
849
|
+
const { user } = useUser();
|
|
850
|
+
const handleClickOutside = useCallback3((event) => {
|
|
851
|
+
const target = event.target;
|
|
852
|
+
if (!target.closest("#civic-dropdown-container")) {
|
|
853
|
+
setIsOpen(false);
|
|
854
|
+
}
|
|
855
|
+
}, []);
|
|
856
|
+
const handleSignOut = useCallback3(() => __async(void 0, null, function* () {
|
|
857
|
+
yield signOut();
|
|
858
|
+
setIsOpen(false);
|
|
859
|
+
}), [signOut]);
|
|
860
|
+
const handleSignIn = useCallback3(() => __async(void 0, null, function* () {
|
|
861
|
+
yield signIn(displayMode);
|
|
862
|
+
setIsOpen(false);
|
|
863
|
+
}), [signIn, displayMode]);
|
|
864
|
+
const handleEscape = useCallback3((event) => {
|
|
865
|
+
if (event.key === "Escape") {
|
|
866
|
+
setIsOpen(false);
|
|
867
|
+
}
|
|
868
|
+
}, []);
|
|
869
|
+
useEffect5(() => {
|
|
870
|
+
if (isOpen) {
|
|
871
|
+
window.addEventListener("click", handleClickOutside);
|
|
872
|
+
window.addEventListener("keydown", handleEscape);
|
|
873
|
+
}
|
|
874
|
+
return () => {
|
|
875
|
+
window.removeEventListener("click", handleClickOutside);
|
|
876
|
+
window.removeEventListener("keydown", handleEscape);
|
|
877
|
+
};
|
|
878
|
+
}, [handleClickOutside, handleEscape, isOpen]);
|
|
879
|
+
if (isAuthenticated) {
|
|
880
|
+
return /* @__PURE__ */ jsxs5("div", { className: "cac-relative", id: "civic-dropdown-container", children: [
|
|
881
|
+
/* @__PURE__ */ jsxs5(
|
|
882
|
+
"button",
|
|
883
|
+
{
|
|
884
|
+
className: cn(
|
|
885
|
+
"cac-flex cac-w-full cac-items-center cac-justify-between cac-gap-2 cac-rounded-full cac-border cac-border-neutral-500 cac-px-3 cac-py-2 cac-text-neutral-500 cac-transition-colors hover:cac-bg-neutral-200 hover:cac-bg-opacity-50",
|
|
886
|
+
className
|
|
887
|
+
),
|
|
888
|
+
onClick: () => setIsOpen((isOpen2) => !isOpen2),
|
|
889
|
+
children: [
|
|
890
|
+
(user == null ? void 0 : user.picture) ? /* @__PURE__ */ jsx12("span", { className: "cac-relative cac-flex cac-h-10 cac-w-10 cac-shrink-0 cac-gap-2 cac-overflow-hidden cac-rounded-full", children: /* @__PURE__ */ jsx12(
|
|
891
|
+
"img",
|
|
892
|
+
{
|
|
893
|
+
className: "cac-h-full cac-w-full cac-object-cover",
|
|
894
|
+
src: user.picture,
|
|
895
|
+
alt: (user == null ? void 0 : user.name) || (user == null ? void 0 : user.email)
|
|
896
|
+
}
|
|
897
|
+
) }) : /* @__PURE__ */ jsx12("div", {}),
|
|
898
|
+
/* @__PURE__ */ jsx12("span", { children: (user == null ? void 0 : user.name) || (user == null ? void 0 : user.email) }),
|
|
899
|
+
isOpen ? /* @__PURE__ */ jsx12(ChevronUp, {}) : /* @__PURE__ */ jsx12(ChevronDown, {})
|
|
900
|
+
]
|
|
901
|
+
}
|
|
902
|
+
),
|
|
903
|
+
/* @__PURE__ */ jsx12(
|
|
904
|
+
"div",
|
|
905
|
+
{
|
|
906
|
+
className: isOpen ? "cac-absolute cac-right-0 cac-mt-2 cac-w-full cac-rounded-lg cac-bg-white cac-py-2 cac-text-neutral-500 cac-shadow-xl" : "cac-hidden",
|
|
907
|
+
children: /* @__PURE__ */ jsx12("ul", { children: /* @__PURE__ */ jsx12("li", { children: /* @__PURE__ */ jsx12(
|
|
908
|
+
"button",
|
|
909
|
+
{
|
|
910
|
+
className: "cac-block cac-w-full cac-px-4 cac-py-2 cac-transition-colors hover:cac-bg-neutral-200 hover:cac-bg-opacity-50",
|
|
911
|
+
onClick: handleSignOut,
|
|
912
|
+
children: "Logout"
|
|
913
|
+
}
|
|
914
|
+
) }) })
|
|
915
|
+
}
|
|
916
|
+
)
|
|
917
|
+
] });
|
|
918
|
+
}
|
|
919
|
+
return /* @__PURE__ */ jsx12(
|
|
920
|
+
"button",
|
|
921
|
+
{
|
|
922
|
+
"data-testid": "sign-in-button",
|
|
923
|
+
className: cn(
|
|
924
|
+
"cac-rounded-full cac-border cac-border-neutral-500 cac-px-3 cac-py-2 cac-transition-colors hover:cac-bg-neutral-200 hover:cac-bg-opacity-50",
|
|
925
|
+
className
|
|
926
|
+
),
|
|
927
|
+
onClick: handleSignIn,
|
|
928
|
+
children: "Sign in"
|
|
929
|
+
}
|
|
930
|
+
);
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
// src/react/components/SignInButton.tsx
|
|
934
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
935
|
+
var SignInButton = ({
|
|
936
|
+
displayMode,
|
|
937
|
+
className
|
|
938
|
+
}) => {
|
|
939
|
+
const { signIn } = useAuth();
|
|
940
|
+
return /* @__PURE__ */ jsx13(
|
|
941
|
+
"button",
|
|
942
|
+
{
|
|
943
|
+
"data-testid": "sign-in-button",
|
|
944
|
+
className: cn(
|
|
945
|
+
"cac-rounded-full cac-border cac-border-neutral-500 cac-px-3 cac-py-2 cac-transition-colors hover:cac-bg-neutral-200 hover:cac-bg-opacity-50",
|
|
946
|
+
className
|
|
947
|
+
),
|
|
948
|
+
onClick: () => signIn(displayMode),
|
|
949
|
+
children: "Sign In"
|
|
950
|
+
}
|
|
951
|
+
);
|
|
952
|
+
};
|
|
953
|
+
|
|
954
|
+
// src/react/components/SignOutButton.tsx
|
|
955
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
956
|
+
var SignOutButton = ({ className }) => {
|
|
957
|
+
const { signOut } = useAuth();
|
|
958
|
+
return /* @__PURE__ */ jsx14(
|
|
959
|
+
"button",
|
|
960
|
+
{
|
|
961
|
+
className: cn(
|
|
962
|
+
"cac-rounded-full cac-border cac-border-neutral-500 cac-px-3 cac-py-2 cac-transition-colors hover:cac-bg-neutral-200 hover:cac-bg-opacity-50",
|
|
963
|
+
className
|
|
964
|
+
),
|
|
965
|
+
onClick: () => signOut(),
|
|
966
|
+
children: "Sign Out"
|
|
967
|
+
}
|
|
968
|
+
);
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
// src/react/components/NextLogOut.tsx
|
|
972
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
973
|
+
var NextLogOut = ({ children }) => {
|
|
974
|
+
const config = resolveAuthConfig();
|
|
975
|
+
const logoutUrl = `${config.logoutUrl}`;
|
|
976
|
+
return /* @__PURE__ */ jsx15("a", { href: logoutUrl, children });
|
|
1086
977
|
};
|
|
1087
978
|
export {
|
|
1088
|
-
|
|
979
|
+
CivicAuthIframeContainer,
|
|
980
|
+
CivicAuthProvider,
|
|
981
|
+
CivicNextAuthProvider,
|
|
982
|
+
NextLogOut,
|
|
983
|
+
SignInButton,
|
|
984
|
+
SignOutButton,
|
|
1089
985
|
UserButton,
|
|
1090
986
|
useAuth,
|
|
1091
|
-
|
|
987
|
+
useConfig,
|
|
988
|
+
useNextUser,
|
|
1092
989
|
useSession,
|
|
1093
990
|
useToken,
|
|
1094
|
-
useUser
|
|
991
|
+
useUser,
|
|
992
|
+
useUserCookie
|
|
1095
993
|
};
|
|
1096
994
|
//# sourceMappingURL=react.mjs.map
|