@foldspace-fe/casdoor-next-auth-kit 0.1.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/dist/billing/index.d.ts +16 -0
- package/dist/billing/index.js +28 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/callback-BTzHQK_r.d.ts +12 -0
- package/dist/casdoor/index.d.ts +28 -0
- package/dist/casdoor/index.js +40 -0
- package/dist/casdoor/index.js.map +1 -0
- package/dist/chunk-6E27SZ7V.js +291 -0
- package/dist/chunk-6E27SZ7V.js.map +1 -0
- package/dist/chunk-DONQHN4U.js +56 -0
- package/dist/chunk-DONQHN4U.js.map +1 -0
- package/dist/chunk-IQEVUR77.js +909 -0
- package/dist/chunk-IQEVUR77.js.map +1 -0
- package/dist/chunk-RGTVPBH7.js +182 -0
- package/dist/chunk-RGTVPBH7.js.map +1 -0
- package/dist/chunk-T2M5MVPE.js +20 -0
- package/dist/chunk-T2M5MVPE.js.map +1 -0
- package/dist/chunk-XMBHIEYL.js +1 -0
- package/dist/chunk-XMBHIEYL.js.map +1 -0
- package/dist/chunk-Y4GJ2AEI.js +192 -0
- package/dist/chunk-Y4GJ2AEI.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +437 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -0
- package/dist/next/index.d.ts +17 -0
- package/dist/next/index.js +24 -0
- package/dist/next/index.js.map +1 -0
- package/dist/options-JUwZSXu2.d.ts +40 -0
- package/dist/react/index.d.ts +242 -0
- package/dist/react/index.js +774 -0
- package/dist/react/index.js.map +1 -0
- package/dist/skills/casdoor-next-auth-kit/SKILL.md +158 -0
- package/dist/skills/casdoor-next-auth-kit/references/casdoor-api-reference.md +2387 -0
- package/dist/skills/casdoor-next-auth-kit/references/swagger.json +3686 -0
- package/dist/types-BPsPs5Rv.d.ts +337 -0
- package/dist/types-DqVXdUge.d.ts +121 -0
- package/package.json +69 -0
|
@@ -0,0 +1,909 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolvePostLoginRedirect
|
|
3
|
+
} from "./chunk-T2M5MVPE.js";
|
|
4
|
+
|
|
5
|
+
// src/core/config.ts
|
|
6
|
+
function normalizeAuthKitConfig(config) {
|
|
7
|
+
return {
|
|
8
|
+
...config,
|
|
9
|
+
casdoor: {
|
|
10
|
+
redirectPath: "/callback",
|
|
11
|
+
signinPath: "/login/oauth/authorize",
|
|
12
|
+
...config.casdoor
|
|
13
|
+
},
|
|
14
|
+
cookie: {
|
|
15
|
+
secure: "auto",
|
|
16
|
+
...config.cookie
|
|
17
|
+
},
|
|
18
|
+
session: {
|
|
19
|
+
maxAgeSeconds: 60 * 60 * 24 * 7,
|
|
20
|
+
...config.session
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/core/public-origin.ts
|
|
26
|
+
var PUBLIC_ORIGIN_COOKIE_NAME = "auth_origin";
|
|
27
|
+
function getRequestOrigin(request, appUrl) {
|
|
28
|
+
const referer = request.headers.get("referer");
|
|
29
|
+
if (referer) {
|
|
30
|
+
try {
|
|
31
|
+
return new URL(referer).origin;
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const origin = request.headers.get("origin");
|
|
36
|
+
if (origin) {
|
|
37
|
+
try {
|
|
38
|
+
return new URL(origin).origin;
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (appUrl) {
|
|
43
|
+
try {
|
|
44
|
+
return new URL(appUrl).origin;
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
|
|
49
|
+
const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
|
|
50
|
+
if (forwardedProto && forwardedHost) {
|
|
51
|
+
return `${forwardedProto}://${forwardedHost}`;
|
|
52
|
+
}
|
|
53
|
+
return new URL(request.url).origin;
|
|
54
|
+
}
|
|
55
|
+
function setPublicOriginCookie(response, origin, secure) {
|
|
56
|
+
response.cookies.set(PUBLIC_ORIGIN_COOKIE_NAME, origin, {
|
|
57
|
+
path: "/",
|
|
58
|
+
httpOnly: true,
|
|
59
|
+
sameSite: "lax",
|
|
60
|
+
secure
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function clearPublicOriginCookie(response, secure) {
|
|
64
|
+
response.cookies.set(PUBLIC_ORIGIN_COOKIE_NAME, "", {
|
|
65
|
+
path: "/",
|
|
66
|
+
httpOnly: true,
|
|
67
|
+
sameSite: "lax",
|
|
68
|
+
secure,
|
|
69
|
+
maxAge: 0
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function getStoredPublicOrigin(request) {
|
|
73
|
+
const cookieHeader = request.headers.get("cookie");
|
|
74
|
+
if (!cookieHeader) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
for (const entry of cookieHeader.split(";")) {
|
|
78
|
+
const [rawName, ...valueParts] = entry.trim().split("=");
|
|
79
|
+
if (rawName === PUBLIC_ORIGIN_COOKIE_NAME) {
|
|
80
|
+
const value = valueParts.join("=").trim();
|
|
81
|
+
if (!value) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
return decodeURIComponent(value);
|
|
86
|
+
} catch {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/core/request-security.ts
|
|
95
|
+
function isSecureRequest(request, appUrl) {
|
|
96
|
+
const url = new URL(request.url);
|
|
97
|
+
if (url.protocol === "https:") return true;
|
|
98
|
+
const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim().toLowerCase();
|
|
99
|
+
if (forwardedProto === "https") return true;
|
|
100
|
+
if (appUrl) {
|
|
101
|
+
try {
|
|
102
|
+
return new URL(appUrl).protocol === "https:";
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/core/auth-redirect.ts
|
|
111
|
+
var AUTH_REDIRECT_COOKIE_NAME = "auth_redirect";
|
|
112
|
+
function getAuthRedirectTarget(request) {
|
|
113
|
+
const cookieHeader = request.headers.get("cookie");
|
|
114
|
+
if (!cookieHeader) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
for (const entry of cookieHeader.split(";")) {
|
|
118
|
+
const [rawName, ...valueParts] = entry.trim().split("=");
|
|
119
|
+
if (rawName === AUTH_REDIRECT_COOKIE_NAME) {
|
|
120
|
+
const value = valueParts.join("=").trim();
|
|
121
|
+
if (!value) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
let decoded = value;
|
|
125
|
+
try {
|
|
126
|
+
decoded = decodeURIComponent(value);
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
if (decoded.startsWith("/") && !decoded.startsWith("//")) {
|
|
130
|
+
return decoded;
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
function setAuthRedirectCookie(response, target, secure) {
|
|
138
|
+
response.cookies.set(AUTH_REDIRECT_COOKIE_NAME, target, {
|
|
139
|
+
path: "/",
|
|
140
|
+
httpOnly: true,
|
|
141
|
+
sameSite: "lax",
|
|
142
|
+
secure
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function clearAuthRedirectCookie(response, secure) {
|
|
146
|
+
response.cookies.set(AUTH_REDIRECT_COOKIE_NAME, "", {
|
|
147
|
+
path: "/",
|
|
148
|
+
httpOnly: true,
|
|
149
|
+
sameSite: "lax",
|
|
150
|
+
secure,
|
|
151
|
+
maxAge: 0
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/core/admin.ts
|
|
156
|
+
var DEFAULT_ADMIN_EMAILS = ["admin@example.com"];
|
|
157
|
+
function readAdminEmailSource() {
|
|
158
|
+
return process.env.GLOBAL_ADMIN_EMAILS || process.env.ADMIN_EMAILS || "";
|
|
159
|
+
}
|
|
160
|
+
function getGlobalAdminEmails() {
|
|
161
|
+
const source = readAdminEmailSource();
|
|
162
|
+
if (!source) {
|
|
163
|
+
return DEFAULT_ADMIN_EMAILS;
|
|
164
|
+
}
|
|
165
|
+
return source.split(",").map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
166
|
+
}
|
|
167
|
+
function isGlobalAdminEmail(email) {
|
|
168
|
+
if (!email) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
return getGlobalAdminEmails().includes(email.toLowerCase());
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/core/index-html.ts
|
|
175
|
+
var DEFAULT_CASDOOR_STATIC_ORIGIN = "https://casdoor-static.foldspace.cn";
|
|
176
|
+
var DEFAULT_CASDOOR_ORIGIN = process.env.NEXT_PUBLIC_CASDOOR_SERVER_URL || "https://auth.heyaai.com";
|
|
177
|
+
var DEFAULT_ICON_HREF = "https://cdn.casbin.org/img/favicon.png";
|
|
178
|
+
var DEFAULT_MANIFEST_HREF = "/manifest.json";
|
|
179
|
+
function escapeHtmlAttribute(value) {
|
|
180
|
+
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
181
|
+
}
|
|
182
|
+
function createAuthIndexHtml(options = {}) {
|
|
183
|
+
const staticOrigin = options.staticOrigin || DEFAULT_CASDOOR_STATIC_ORIGIN;
|
|
184
|
+
const casdoorOrigin = options.casdoorOrigin || DEFAULT_CASDOOR_ORIGIN;
|
|
185
|
+
const apiProxyPrefix = options.apiProxyPrefix || "/auth/";
|
|
186
|
+
const appName = options.appName || "\u521B\u5C0F\u5267 AI";
|
|
187
|
+
const organizationName = options.organizationName || "built-in";
|
|
188
|
+
const description = options.description || "\u521B\u5C0F\u5267 AI \u767B\u5F55 - \u4E00\u4E2A\u652F\u6301 OAuth 2.0\u3001OIDC\u3001SAML \u548C CAS \u7684\u8EAB\u4EFD\u4E0E\u5355\u70B9\u767B\u5F55\u5E73\u53F0";
|
|
189
|
+
const iconHref = options.iconHref || DEFAULT_ICON_HREF;
|
|
190
|
+
const manifestHref = options.manifestHref || DEFAULT_MANIFEST_HREF;
|
|
191
|
+
const mainJs = `${staticOrigin}/static/js/main.5ddbc6ff.js`;
|
|
192
|
+
const mainCss = `${staticOrigin}/static/css/main.f35879a1.css`;
|
|
193
|
+
return String.raw`<!doctype html>
|
|
194
|
+
<html lang="zh-CN">
|
|
195
|
+
<head>
|
|
196
|
+
<meta charset="utf-8" />
|
|
197
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
198
|
+
<meta name="theme-color" content="#000000" />
|
|
199
|
+
<meta name="description" content="${escapeHtmlAttribute(description)}" />
|
|
200
|
+
<link rel="apple-touch-icon" href="${escapeHtmlAttribute(iconHref)}" />
|
|
201
|
+
<link rel="manifest" href="${escapeHtmlAttribute(manifestHref)}" />
|
|
202
|
+
<title>${escapeHtmlAttribute(appName)}</title>
|
|
203
|
+
<script>
|
|
204
|
+
(function () {
|
|
205
|
+
var cdnOrigin = ${JSON.stringify(staticOrigin)}
|
|
206
|
+
var casdoorOrigin = ${JSON.stringify(casdoorOrigin)}
|
|
207
|
+
var currentOrigin = window.location.origin
|
|
208
|
+
var proxyPrefix = ${JSON.stringify(apiProxyPrefix)}
|
|
209
|
+
var proxyPathPrefix = proxyPrefix.replace(/\/$/, '')
|
|
210
|
+
var applicationId = ${JSON.stringify((options.organizationName || "built-in") + "/" + (options.appName || "\u521B\u5C0F\u5267 AI"))}
|
|
211
|
+
|
|
212
|
+
function toProxyUrl(input) {
|
|
213
|
+
try {
|
|
214
|
+
var url = typeof input === 'string' ? new URL(input, window.location.href) : input instanceof URL ? input : null
|
|
215
|
+
if (!url) {
|
|
216
|
+
return input
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (url.origin === cdnOrigin && url.pathname.indexOf(proxyPrefix) === 0) {
|
|
220
|
+
return currentOrigin + url.pathname + url.search + url.hash
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (url.origin === currentOrigin && url.pathname.indexOf('/static/') === 0) {
|
|
224
|
+
return cdnOrigin + url.pathname + url.search + url.hash
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (url.origin === currentOrigin && (url.pathname === '/auth' || url.pathname.indexOf('/auth/') === 0)) {
|
|
228
|
+
if (url.pathname === '/auth/api/get-application') {
|
|
229
|
+
url.searchParams.set('id', applicationId)
|
|
230
|
+
}
|
|
231
|
+
return currentOrigin + proxyPathPrefix + url.pathname.slice('/auth'.length) + url.search + url.hash
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (url.origin === casdoorOrigin) {
|
|
235
|
+
return currentOrigin + proxyPathPrefix + url.pathname + url.search + url.hash
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
return input
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return input
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function rewriteElement(element) {
|
|
245
|
+
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
|
|
246
|
+
return
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (element.tagName === 'A' && element.getAttribute('href')) {
|
|
250
|
+
var href = element.getAttribute('href')
|
|
251
|
+
var rewrittenHref = toProxyUrl(href)
|
|
252
|
+
if (rewrittenHref !== href) {
|
|
253
|
+
element.setAttribute('href', rewrittenHref)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (element.tagName === 'FORM' && element.getAttribute('action')) {
|
|
258
|
+
var action = element.getAttribute('action')
|
|
259
|
+
var rewrittenAction = toProxyUrl(action)
|
|
260
|
+
if (rewrittenAction !== action) {
|
|
261
|
+
element.setAttribute('action', rewrittenAction)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (element.tagName === 'SCRIPT' && element.getAttribute('src')) {
|
|
266
|
+
var scriptSrc = element.getAttribute('src')
|
|
267
|
+
var rewrittenScriptSrc = toProxyUrl(scriptSrc)
|
|
268
|
+
if (rewrittenScriptSrc !== scriptSrc) {
|
|
269
|
+
element.setAttribute('src', rewrittenScriptSrc)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (element.tagName === 'LINK' && element.getAttribute('href')) {
|
|
274
|
+
var linkHref = element.getAttribute('href')
|
|
275
|
+
var rewrittenLinkHref = toProxyUrl(linkHref)
|
|
276
|
+
if (rewrittenLinkHref !== linkHref) {
|
|
277
|
+
element.setAttribute('href', rewrittenLinkHref)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (element.tagName === 'IMG' && element.getAttribute('src')) {
|
|
282
|
+
var imgSrc = element.getAttribute('src')
|
|
283
|
+
var rewrittenImgSrc = toProxyUrl(imgSrc)
|
|
284
|
+
if (rewrittenImgSrc !== imgSrc) {
|
|
285
|
+
element.setAttribute('src', rewrittenImgSrc)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (typeof element.querySelectorAll === 'function') {
|
|
290
|
+
element.querySelectorAll('a[href], form[action], script[src], link[href], img[src]').forEach(rewriteElement)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (typeof window.fetch === 'function') {
|
|
295
|
+
var originalFetch = window.fetch.bind(window)
|
|
296
|
+
window.fetch = function (input, init) {
|
|
297
|
+
return originalFetch(toProxyUrl(input), init)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) {
|
|
302
|
+
var originalOpen = window.XMLHttpRequest.prototype.open
|
|
303
|
+
window.XMLHttpRequest.prototype.open = function (method, url) {
|
|
304
|
+
var rewrittenUrl = toProxyUrl(url)
|
|
305
|
+
return originalOpen.apply(this, [method, rewrittenUrl].concat(Array.prototype.slice.call(arguments, 2)))
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (window.open) {
|
|
310
|
+
var originalOpenWindow = window.open.bind(window)
|
|
311
|
+
window.open = function (url) {
|
|
312
|
+
return originalOpenWindow(toProxyUrl(url), arguments[1], arguments[2])
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (window.location && typeof window.location.assign === 'function') {
|
|
317
|
+
var originalAssign = window.location.assign.bind(window.location)
|
|
318
|
+
window.location.assign = function (url) {
|
|
319
|
+
return originalAssign(toProxyUrl(url))
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (window.location && typeof window.location.replace === 'function') {
|
|
324
|
+
var originalReplace = window.location.replace.bind(window.location)
|
|
325
|
+
window.location.replace = function (url) {
|
|
326
|
+
return originalReplace(toProxyUrl(url))
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (window.HTMLFormElement && window.HTMLFormElement.prototype) {
|
|
331
|
+
var originalSubmit = window.HTMLFormElement.prototype.submit
|
|
332
|
+
window.HTMLFormElement.prototype.submit = function () {
|
|
333
|
+
if (this.action) {
|
|
334
|
+
this.action = toProxyUrl(this.action)
|
|
335
|
+
}
|
|
336
|
+
return originalSubmit.apply(this, arguments)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
document.addEventListener('click', function (event) {
|
|
341
|
+
var target = event.target instanceof Element ? event.target.closest('a[href]') : null
|
|
342
|
+
if (!target) {
|
|
343
|
+
return
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
var href = target.getAttribute('href')
|
|
347
|
+
var rewritten = toProxyUrl(href)
|
|
348
|
+
if (rewritten !== href) {
|
|
349
|
+
event.preventDefault()
|
|
350
|
+
window.location.href = rewritten
|
|
351
|
+
}
|
|
352
|
+
}, true)
|
|
353
|
+
|
|
354
|
+
document.addEventListener('submit', function (event) {
|
|
355
|
+
var form = event.target instanceof HTMLFormElement ? event.target : null
|
|
356
|
+
if (!form || !form.action) {
|
|
357
|
+
return
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
var rewritten = toProxyUrl(form.action)
|
|
361
|
+
if (rewritten !== form.action) {
|
|
362
|
+
event.preventDefault()
|
|
363
|
+
form.action = rewritten
|
|
364
|
+
form.submit()
|
|
365
|
+
}
|
|
366
|
+
}, true)
|
|
367
|
+
|
|
368
|
+
var originalAppendChild = Node.prototype.appendChild
|
|
369
|
+
Node.prototype.appendChild = function (node) {
|
|
370
|
+
rewriteElement(node)
|
|
371
|
+
return originalAppendChild.call(this, node)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
var originalInsertBefore = Node.prototype.insertBefore
|
|
375
|
+
Node.prototype.insertBefore = function (node, referenceNode) {
|
|
376
|
+
rewriteElement(node)
|
|
377
|
+
return originalInsertBefore.call(this, node, referenceNode)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (document.body) {
|
|
381
|
+
rewriteElement(document.body)
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (window.MutationObserver) {
|
|
385
|
+
var observer = new MutationObserver(function (mutations) {
|
|
386
|
+
mutations.forEach(function (mutation) {
|
|
387
|
+
mutation.addedNodes.forEach(rewriteElement)
|
|
388
|
+
})
|
|
389
|
+
})
|
|
390
|
+
observer.observe(document.documentElement, { childList: true, subtree: true })
|
|
391
|
+
}
|
|
392
|
+
})()
|
|
393
|
+
</script>
|
|
394
|
+
<script defer="defer" src="${escapeHtmlAttribute(mainJs)}"></script>
|
|
395
|
+
<link href="${escapeHtmlAttribute(mainCss)}" rel="stylesheet" />
|
|
396
|
+
</head>
|
|
397
|
+
<body>
|
|
398
|
+
<noscript>你需要启用 JavaScript 才能继续。</noscript>
|
|
399
|
+
<div id="root"></div>
|
|
400
|
+
</body>
|
|
401
|
+
</html>
|
|
402
|
+
`;
|
|
403
|
+
}
|
|
404
|
+
var AUTH_INDEX_HTML = createAuthIndexHtml();
|
|
405
|
+
|
|
406
|
+
// src/core/oauth-state.ts
|
|
407
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
408
|
+
import crypto2 from "crypto";
|
|
409
|
+
var STATE_EXPIRY_SECONDS = 600;
|
|
410
|
+
var STATE_SECRET = process.env.NEXTAUTH_SECRET || process.env.CASDOOR_CLIENT_SECRET || "dev-state-secret";
|
|
411
|
+
var pkceCookiePrefix = "pkce_code_verifier";
|
|
412
|
+
function signStatePayload(payload) {
|
|
413
|
+
const body = Buffer2.from(JSON.stringify(payload)).toString("base64url");
|
|
414
|
+
const signature = crypto2.createHmac("sha256", STATE_SECRET).update(body).digest("base64url");
|
|
415
|
+
return `${body}.${signature}`;
|
|
416
|
+
}
|
|
417
|
+
function decodeStatePayload(state) {
|
|
418
|
+
const [body, signature] = state.split(".");
|
|
419
|
+
if (!body || !signature) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
const expectedSignature = crypto2.createHmac("sha256", STATE_SECRET).update(body).digest("base64url");
|
|
423
|
+
if (expectedSignature.length !== signature.length || !crypto2.timingSafeEqual(Buffer2.from(expectedSignature), Buffer2.from(signature))) {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
try {
|
|
427
|
+
return JSON.parse(Buffer2.from(body, "base64url").toString("utf8"));
|
|
428
|
+
} catch {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function generateStateToken() {
|
|
433
|
+
return signStatePayload({
|
|
434
|
+
nonce: crypto2.randomUUID(),
|
|
435
|
+
issuedAt: Date.now()
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
function getPkceCookieName(state) {
|
|
439
|
+
const digest = crypto2.createHash("sha256").update(state).digest("base64url");
|
|
440
|
+
return `${pkceCookiePrefix}.${digest}`;
|
|
441
|
+
}
|
|
442
|
+
async function verifyState(stateFromUrl) {
|
|
443
|
+
const payload = decodeStatePayload(stateFromUrl);
|
|
444
|
+
if (!payload) {
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
return Date.now() - payload.issuedAt <= STATE_EXPIRY_SECONDS * 1e3;
|
|
448
|
+
}
|
|
449
|
+
function parseStateToken(token) {
|
|
450
|
+
if (!token) return null;
|
|
451
|
+
return decodeStatePayload(token);
|
|
452
|
+
}
|
|
453
|
+
function verifyStateToken(token) {
|
|
454
|
+
if (!token) return false;
|
|
455
|
+
return Boolean(decodeStatePayload(token));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/core/session-token.ts
|
|
459
|
+
import { Buffer as Buffer3 } from "buffer";
|
|
460
|
+
import crypto3 from "crypto";
|
|
461
|
+
var DEFAULT_MAX_AGE = 30 * 24 * 60 * 60;
|
|
462
|
+
function base64UrlEncode(value) {
|
|
463
|
+
return Buffer3.from(value, "utf8").toString("base64url");
|
|
464
|
+
}
|
|
465
|
+
function base64UrlDecode(value) {
|
|
466
|
+
return Buffer3.from(value, "base64url").toString("utf8");
|
|
467
|
+
}
|
|
468
|
+
function createSignature(input, secret) {
|
|
469
|
+
return crypto3.createHmac("sha256", secret).update(input).digest("base64url");
|
|
470
|
+
}
|
|
471
|
+
function timingSafeEqual(left, right) {
|
|
472
|
+
const leftBuffer = Buffer3.from(left);
|
|
473
|
+
const rightBuffer = Buffer3.from(right);
|
|
474
|
+
if (leftBuffer.length !== rightBuffer.length) {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
return crypto3.timingSafeEqual(leftBuffer, rightBuffer);
|
|
478
|
+
}
|
|
479
|
+
async function encodeSessionToken(params) {
|
|
480
|
+
const { token = {}, secret, maxAge = DEFAULT_MAX_AGE } = params;
|
|
481
|
+
const issuedAt = Math.floor(Date.now() / 1e3);
|
|
482
|
+
const header = base64UrlEncode(JSON.stringify({ alg: "HS256", typ: "JWT" }));
|
|
483
|
+
const payload = base64UrlEncode(
|
|
484
|
+
JSON.stringify({
|
|
485
|
+
...token,
|
|
486
|
+
iat: issuedAt,
|
|
487
|
+
exp: issuedAt + maxAge,
|
|
488
|
+
jti: crypto3.randomUUID()
|
|
489
|
+
})
|
|
490
|
+
);
|
|
491
|
+
const signature = createSignature(`${header}.${payload}`, secret);
|
|
492
|
+
return `${header}.${payload}.${signature}`;
|
|
493
|
+
}
|
|
494
|
+
async function decodeSessionToken(params) {
|
|
495
|
+
const { token, secret } = params;
|
|
496
|
+
if (!token) {
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
const [header, payload, signature] = token.split(".");
|
|
500
|
+
if (!header || !payload || !signature) {
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
const expectedSignature = createSignature(`${header}.${payload}`, secret);
|
|
504
|
+
if (!timingSafeEqual(signature, expectedSignature)) {
|
|
505
|
+
return null;
|
|
506
|
+
}
|
|
507
|
+
try {
|
|
508
|
+
const parsedPayload = JSON.parse(base64UrlDecode(payload));
|
|
509
|
+
if (parsedPayload.exp && parsedPayload.exp <= Math.floor(Date.now() / 1e3)) {
|
|
510
|
+
return null;
|
|
511
|
+
}
|
|
512
|
+
return parsedPayload;
|
|
513
|
+
} catch {
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// src/casdoor/config.ts
|
|
519
|
+
function getCasdoorConfig(config) {
|
|
520
|
+
return normalizeAuthKitConfig(config);
|
|
521
|
+
}
|
|
522
|
+
function getCasdoorAuthorizeUrl(config, params) {
|
|
523
|
+
const base = new URL(config.casdoor.signinPath ?? "/login/oauth/authorize", config.casdoor.serverUrl);
|
|
524
|
+
base.searchParams.set("response_type", "code");
|
|
525
|
+
base.searchParams.set("client_id", config.casdoor.clientId);
|
|
526
|
+
base.searchParams.set("redirect_uri", params.redirectUri);
|
|
527
|
+
base.searchParams.set("scope", "profile");
|
|
528
|
+
base.searchParams.set("state", params.state);
|
|
529
|
+
base.searchParams.set("code_challenge", params.codeChallenge);
|
|
530
|
+
base.searchParams.set("code_challenge_method", "S256");
|
|
531
|
+
if (params.kind === "signup") {
|
|
532
|
+
base.searchParams.set("action", "signup");
|
|
533
|
+
}
|
|
534
|
+
return base.toString();
|
|
535
|
+
}
|
|
536
|
+
function getCasdoorTokenUrl(config) {
|
|
537
|
+
return new URL("/api/login/oauth/access_token", config.casdoor.serverUrl).toString();
|
|
538
|
+
}
|
|
539
|
+
function getCasdoorUserInfoUrl(config) {
|
|
540
|
+
return new URL("/api/userinfo", config.casdoor.serverUrl).toString();
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// src/casdoor/oauth.ts
|
|
544
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
545
|
+
function decodeJwtPayload(token) {
|
|
546
|
+
const parts = token.split(".");
|
|
547
|
+
if (parts.length < 2) {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
try {
|
|
551
|
+
const payload = parts[1];
|
|
552
|
+
return JSON.parse(Buffer4.from(payload, "base64url").toString("utf8"));
|
|
553
|
+
} catch {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
async function exchangeCodeForToken(config, code, redirectUri, codeVerifier) {
|
|
558
|
+
const response = await fetch(getCasdoorTokenUrl(config), {
|
|
559
|
+
method: "POST",
|
|
560
|
+
headers: { "content-type": "application/json" },
|
|
561
|
+
body: JSON.stringify({
|
|
562
|
+
grant_type: "authorization_code",
|
|
563
|
+
client_id: config.casdoor.clientId,
|
|
564
|
+
client_secret: config.casdoor.clientSecret,
|
|
565
|
+
code,
|
|
566
|
+
redirect_uri: redirectUri,
|
|
567
|
+
code_verifier: codeVerifier
|
|
568
|
+
})
|
|
569
|
+
});
|
|
570
|
+
if (!response.ok) {
|
|
571
|
+
throw new Error("Failed to exchange Casdoor authorization code.");
|
|
572
|
+
}
|
|
573
|
+
return await response.json();
|
|
574
|
+
}
|
|
575
|
+
async function fetchCasdoorUserInfo(config, accessToken) {
|
|
576
|
+
const response = await fetch(getCasdoorUserInfoUrl(config), {
|
|
577
|
+
headers: {
|
|
578
|
+
authorization: "Bearer " + accessToken
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
if (!response.ok) {
|
|
582
|
+
throw new Error("Failed to fetch Casdoor user profile.");
|
|
583
|
+
}
|
|
584
|
+
return await response.json();
|
|
585
|
+
}
|
|
586
|
+
function decodeCasdoorAccessToken(accessToken) {
|
|
587
|
+
return decodeJwtPayload(accessToken);
|
|
588
|
+
}
|
|
589
|
+
var exchangeCasdoorOAuthToken = exchangeCodeForToken;
|
|
590
|
+
|
|
591
|
+
// src/casdoor/entry.ts
|
|
592
|
+
import { NextResponse } from "next/server";
|
|
593
|
+
|
|
594
|
+
// src/core/pkce.ts
|
|
595
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
|
|
596
|
+
function toBase64Url(bytes) {
|
|
597
|
+
const raw = Buffer.from(bytes).toString("base64");
|
|
598
|
+
return raw.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
599
|
+
}
|
|
600
|
+
async function createPkcePair() {
|
|
601
|
+
const bytes = crypto.getRandomValues(new Uint8Array(48));
|
|
602
|
+
const verifier = Array.from(bytes, (byte) => chars[byte % chars.length]).join("");
|
|
603
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
|
|
604
|
+
return { verifier, challenge: toBase64Url(digest) };
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// src/casdoor/entry.ts
|
|
608
|
+
function buildLocalAuthorizeUrl(origin, config, params) {
|
|
609
|
+
const normalized = normalizeAuthKitConfig(config);
|
|
610
|
+
const authorizePath = params.kind === "signup" ? "/signup/oauth/authorize" : normalized.casdoor.signinPath || "/login/oauth/authorize";
|
|
611
|
+
const authorizeUrl = new URL(authorizePath, origin);
|
|
612
|
+
authorizeUrl.searchParams.set("response_type", "code");
|
|
613
|
+
authorizeUrl.searchParams.set("client_id", normalized.casdoor.clientId);
|
|
614
|
+
authorizeUrl.searchParams.set("redirect_uri", `${origin}${normalized.casdoor.redirectPath || "/callback"}`);
|
|
615
|
+
authorizeUrl.searchParams.set("scope", "profile");
|
|
616
|
+
authorizeUrl.searchParams.set("state", params.state);
|
|
617
|
+
authorizeUrl.searchParams.set("code_challenge", params.codeChallenge);
|
|
618
|
+
authorizeUrl.searchParams.set("code_challenge_method", "S256");
|
|
619
|
+
return authorizeUrl.toString();
|
|
620
|
+
}
|
|
621
|
+
async function createRedirectEntryResponse(request, config, kind) {
|
|
622
|
+
const normalized = normalizeAuthKitConfig(config);
|
|
623
|
+
const origin = getRequestOrigin(request, normalized.appUrl);
|
|
624
|
+
const secure = normalized.cookie?.secure === "auto" ? isSecureRequest(request, normalized.appUrl) : Boolean(normalized.cookie?.secure);
|
|
625
|
+
const { verifier, challenge } = await createPkcePair();
|
|
626
|
+
const state = generateStateToken();
|
|
627
|
+
const response = NextResponse.redirect(
|
|
628
|
+
buildLocalAuthorizeUrl(origin, normalized, { state, codeChallenge: challenge, kind }),
|
|
629
|
+
307
|
|
630
|
+
);
|
|
631
|
+
const redirectTarget = getAuthRedirectTarget(request);
|
|
632
|
+
if (redirectTarget) {
|
|
633
|
+
setAuthRedirectCookie(response, redirectTarget, secure);
|
|
634
|
+
}
|
|
635
|
+
setPublicOriginCookie(response, origin, secure);
|
|
636
|
+
response.cookies.set("oauth_state", state, { httpOnly: true, sameSite: "lax", secure, path: "/" });
|
|
637
|
+
response.cookies.set(getPkceCookieName(state), verifier, { httpOnly: true, sameSite: "lax", secure, path: "/" });
|
|
638
|
+
return response;
|
|
639
|
+
}
|
|
640
|
+
async function createAuthorizePageResponse(request, config) {
|
|
641
|
+
const normalized = normalizeAuthKitConfig(config);
|
|
642
|
+
const origin = getRequestOrigin(request, normalized.appUrl);
|
|
643
|
+
const secure = normalized.cookie?.secure === "auto" ? isSecureRequest(request, normalized.appUrl) : Boolean(normalized.cookie?.secure);
|
|
644
|
+
const response = new NextResponse(
|
|
645
|
+
createAuthIndexHtml({
|
|
646
|
+
appName: normalized.casdoor.appName,
|
|
647
|
+
organizationName: normalized.casdoor.organizationName,
|
|
648
|
+
staticOrigin: process.env.NEXT_PUBLIC_CASDOOR_STATIC_ORIGIN,
|
|
649
|
+
casdoorOrigin: normalized.casdoor.serverUrl,
|
|
650
|
+
apiProxyPrefix: "/auth/"
|
|
651
|
+
}),
|
|
652
|
+
{
|
|
653
|
+
status: 200,
|
|
654
|
+
headers: {
|
|
655
|
+
"content-type": "text/html; charset=utf-8",
|
|
656
|
+
"cache-control": "no-store, max-age=0"
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
);
|
|
660
|
+
setPublicOriginCookie(response, origin, secure);
|
|
661
|
+
return response;
|
|
662
|
+
}
|
|
663
|
+
async function createLoginEntryResponse(request, config) {
|
|
664
|
+
return createRedirectEntryResponse(request, config, "login");
|
|
665
|
+
}
|
|
666
|
+
async function createSignupEntryResponse(request, config) {
|
|
667
|
+
return createRedirectEntryResponse(request, config, "signup");
|
|
668
|
+
}
|
|
669
|
+
async function createAuthorizeEntryResponse(request, config) {
|
|
670
|
+
return createAuthorizePageResponse(request, config);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// src/casdoor/callback.ts
|
|
674
|
+
import { NextResponse as NextResponse2 } from "next/server";
|
|
675
|
+
function readCookieHeaderValue(cookieHeader, name) {
|
|
676
|
+
if (!cookieHeader) {
|
|
677
|
+
return null;
|
|
678
|
+
}
|
|
679
|
+
for (const entry of cookieHeader.split(";")) {
|
|
680
|
+
const [rawName, ...valueParts] = entry.trim().split("=");
|
|
681
|
+
if (rawName === name) {
|
|
682
|
+
const value = valueParts.join("=").trim();
|
|
683
|
+
return value || null;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
function getPublicOrigin(request, config) {
|
|
689
|
+
return getStoredPublicOrigin(request) || getRequestOrigin(request, config.appUrl);
|
|
690
|
+
}
|
|
691
|
+
function rewriteToCallbackErrorPage(request, config, title, message, details) {
|
|
692
|
+
const origin = getPublicOrigin(request, config);
|
|
693
|
+
const targetUrl = new URL("/callback/error", origin);
|
|
694
|
+
targetUrl.searchParams.set("title", title);
|
|
695
|
+
targetUrl.searchParams.set("message", message);
|
|
696
|
+
if (details) {
|
|
697
|
+
targetUrl.searchParams.set("details", details);
|
|
698
|
+
}
|
|
699
|
+
return NextResponse2.redirect(targetUrl, 307);
|
|
700
|
+
}
|
|
701
|
+
function getPkceCodeVerifier(request, state) {
|
|
702
|
+
return readCookieHeaderValue(request.headers.get("cookie"), getPkceCookieName(state));
|
|
703
|
+
}
|
|
704
|
+
function setNextAuthSessionCookies(response, sessionToken, isSecure) {
|
|
705
|
+
const cookieName = isSecure ? "__Secure-next-auth.session-token" : "next-auth.session-token";
|
|
706
|
+
const expires = new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3);
|
|
707
|
+
const baseOptions = {
|
|
708
|
+
path: "/",
|
|
709
|
+
httpOnly: true,
|
|
710
|
+
sameSite: "lax",
|
|
711
|
+
secure: isSecure,
|
|
712
|
+
expires
|
|
713
|
+
};
|
|
714
|
+
const maxCookieSize = 3933;
|
|
715
|
+
if (sessionToken.length <= maxCookieSize) {
|
|
716
|
+
response.cookies.set(cookieName, sessionToken, baseOptions);
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
const chunkCount = Math.ceil(sessionToken.length / maxCookieSize);
|
|
720
|
+
for (let index = 0; index < chunkCount; index++) {
|
|
721
|
+
response.cookies.set(
|
|
722
|
+
`${cookieName}.${index}`,
|
|
723
|
+
sessionToken.slice(index * maxCookieSize, (index + 1) * maxCookieSize),
|
|
724
|
+
baseOptions
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
function sanitizeRedirectPath(value) {
|
|
729
|
+
if (!value || !value.startsWith("/") || value.startsWith("//")) {
|
|
730
|
+
return "/user/account";
|
|
731
|
+
}
|
|
732
|
+
return value;
|
|
733
|
+
}
|
|
734
|
+
function mapProfileToAuthUser(profile, adapter) {
|
|
735
|
+
const typedProfile = profile;
|
|
736
|
+
const email = typedProfile.email || null;
|
|
737
|
+
const isAdmin = Boolean(typedProfile.isAdmin) || Boolean(adapter?.isAdminEmail?.(email)) || isGlobalAdminEmail(email);
|
|
738
|
+
return {
|
|
739
|
+
id: typedProfile.sub || typedProfile.id || typedProfile.email || "casdoor-user",
|
|
740
|
+
name: typedProfile.name || typedProfile.displayName || null,
|
|
741
|
+
email,
|
|
742
|
+
image: typedProfile.picture || typedProfile.avatarUrl || null,
|
|
743
|
+
isAdmin,
|
|
744
|
+
tokenBalance: 2580,
|
|
745
|
+
isVip: true
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
function getRedirectTarget(request, user, adapter) {
|
|
749
|
+
const adapterRedirect = adapter?.resolvePostLoginRedirect?.(user);
|
|
750
|
+
if (adapterRedirect) {
|
|
751
|
+
return sanitizeRedirectPath(adapterRedirect);
|
|
752
|
+
}
|
|
753
|
+
const storedRedirect = getAuthRedirectTarget(request);
|
|
754
|
+
if (storedRedirect) {
|
|
755
|
+
return sanitizeRedirectPath(storedRedirect);
|
|
756
|
+
}
|
|
757
|
+
return sanitizeRedirectPath(resolvePostLoginRedirect(user, "/user/account"));
|
|
758
|
+
}
|
|
759
|
+
async function createCallbackResponse(request, options) {
|
|
760
|
+
const normalized = normalizeAuthKitConfig(options.config);
|
|
761
|
+
const publicOrigin = getPublicOrigin(request, normalized);
|
|
762
|
+
const url = new URL(request.url);
|
|
763
|
+
const code = url.searchParams.get("code");
|
|
764
|
+
const state = url.searchParams.get("state");
|
|
765
|
+
const error = url.searchParams.get("error");
|
|
766
|
+
const secure = normalized.cookie?.secure === "auto" ? isSecureRequest(request, normalized.appUrl) : Boolean(normalized.cookie?.secure);
|
|
767
|
+
if (error) {
|
|
768
|
+
return rewriteToCallbackErrorPage(
|
|
769
|
+
request,
|
|
770
|
+
normalized,
|
|
771
|
+
"Casdoor \u8FD4\u56DE\u4E86\u6388\u6743\u9519\u8BEF",
|
|
772
|
+
"\u6388\u6743\u670D\u52A1\u5668\u5728\u56DE\u8C03\u9636\u6BB5\u8FD4\u56DE\u4E86\u9519\u8BEF\u4FE1\u606F\u3002\u8BF7\u8FD4\u56DE\u9996\u9875\u6216\u91CD\u65B0\u767B\u5F55\u540E\u518D\u8BD5\u3002",
|
|
773
|
+
error
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
if (!code) {
|
|
777
|
+
return rewriteToCallbackErrorPage(
|
|
778
|
+
request,
|
|
779
|
+
normalized,
|
|
780
|
+
"\u7F3A\u5C11\u6388\u6743\u7801",
|
|
781
|
+
"Casdoor \u56DE\u8C03\u6CA1\u6709\u5E26\u56DE code\uFF0C\u8FD9\u901A\u5E38\u610F\u5473\u7740\u6388\u6743\u6D41\u7A0B\u672A\u5B8C\u6210\u3002",
|
|
782
|
+
"no_code"
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
if (!state || !await verifyState(state)) {
|
|
786
|
+
return rewriteToCallbackErrorPage(
|
|
787
|
+
request,
|
|
788
|
+
normalized,
|
|
789
|
+
"\u767B\u5F55\u72B6\u6001\u6821\u9A8C\u5931\u8D25",
|
|
790
|
+
"\u56DE\u8C03\u4E2D\u7684 state \u4E0E\u672C\u6B21\u767B\u5F55\u6D41\u7A0B\u4E0D\u5339\u914D\uFF0C\u8BF7\u91CD\u65B0\u53D1\u8D77\u767B\u5F55\u3002",
|
|
791
|
+
"invalid_state"
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
const codeVerifier = getPkceCodeVerifier(request, state);
|
|
795
|
+
if (!codeVerifier) {
|
|
796
|
+
return rewriteToCallbackErrorPage(
|
|
797
|
+
request,
|
|
798
|
+
normalized,
|
|
799
|
+
"\u7F3A\u5C11 PKCE \u6821\u9A8C\u503C",
|
|
800
|
+
"\u56DE\u8C03\u8BF7\u6C42\u91CC\u6CA1\u6709\u627E\u5230 pkce_code_verifier cookie\u3002\u8BF7\u91CD\u65B0\u4ECE\u767B\u5F55\u5165\u53E3\u53D1\u8D77\u6D41\u7A0B\u3002",
|
|
801
|
+
"missing_pkce_code_verifier"
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
const casdoorConfig = getCasdoorConfig(normalized);
|
|
805
|
+
const redirectUri = `${publicOrigin}${casdoorConfig.casdoor.redirectPath}`;
|
|
806
|
+
const tokens = await exchangeCasdoorOAuthToken(casdoorConfig, code, redirectUri, codeVerifier);
|
|
807
|
+
const accessToken = tokens.access_token ?? tokens.accessToken ?? "";
|
|
808
|
+
if (!accessToken) {
|
|
809
|
+
return rewriteToCallbackErrorPage(
|
|
810
|
+
request,
|
|
811
|
+
normalized,
|
|
812
|
+
"\u7F3A\u5C11\u8BBF\u95EE\u4EE4\u724C",
|
|
813
|
+
"Casdoor \u56DE\u8C03\u6CA1\u6709\u8FD4\u56DE access token\u3002",
|
|
814
|
+
"missing_access_token"
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
const profile = await fetchCasdoorUserInfo(casdoorConfig, accessToken);
|
|
818
|
+
const decodedAccessToken = decodeCasdoorAccessToken(accessToken);
|
|
819
|
+
const mappedUser = options.adapter?.onUserSync ? await options.adapter.onUserSync(profile, {
|
|
820
|
+
accessToken,
|
|
821
|
+
refreshToken: tokens.refresh_token || tokens.refreshToken,
|
|
822
|
+
idToken: tokens.id_token || tokens.idToken,
|
|
823
|
+
expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : tokens.expiresAt
|
|
824
|
+
}) : mapProfileToAuthUser(profile, options.adapter);
|
|
825
|
+
if (options.persistence?.syncAuthUser) {
|
|
826
|
+
await options.persistence.syncAuthUser(mappedUser);
|
|
827
|
+
}
|
|
828
|
+
const sessionToken = await encodeSessionToken({
|
|
829
|
+
token: {
|
|
830
|
+
id: mappedUser.id,
|
|
831
|
+
sub: mappedUser.id,
|
|
832
|
+
userId: mappedUser.id,
|
|
833
|
+
name: mappedUser.name,
|
|
834
|
+
email: mappedUser.email,
|
|
835
|
+
picture: mappedUser.image,
|
|
836
|
+
accessToken,
|
|
837
|
+
expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : decodedAccessToken?.exp,
|
|
838
|
+
isAdmin: mappedUser.isAdmin,
|
|
839
|
+
tokenBalance: mappedUser.tokenBalance,
|
|
840
|
+
isVip: mappedUser.isVip
|
|
841
|
+
},
|
|
842
|
+
secret: normalized.nextauthSecret,
|
|
843
|
+
maxAge: normalized.session?.maxAgeSeconds
|
|
844
|
+
});
|
|
845
|
+
const response = NextResponse2.redirect(new URL(getRedirectTarget(request, mappedUser, options.adapter), publicOrigin));
|
|
846
|
+
setNextAuthSessionCookies(response, sessionToken, secure);
|
|
847
|
+
response.cookies.set(getPkceCookieName(state), "", {
|
|
848
|
+
path: "/",
|
|
849
|
+
httpOnly: true,
|
|
850
|
+
sameSite: "lax",
|
|
851
|
+
secure,
|
|
852
|
+
maxAge: 0
|
|
853
|
+
});
|
|
854
|
+
response.cookies.set("oauth_state", "", {
|
|
855
|
+
path: "/",
|
|
856
|
+
httpOnly: true,
|
|
857
|
+
sameSite: "lax",
|
|
858
|
+
secure,
|
|
859
|
+
maxAge: 0
|
|
860
|
+
});
|
|
861
|
+
clearAuthRedirectCookie(response, secure);
|
|
862
|
+
clearPublicOriginCookie(response, secure);
|
|
863
|
+
return response;
|
|
864
|
+
}
|
|
865
|
+
function createCallbackHandler(options) {
|
|
866
|
+
return async function GET(request) {
|
|
867
|
+
return createCallbackResponse(request, options);
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
export {
|
|
872
|
+
normalizeAuthKitConfig,
|
|
873
|
+
PUBLIC_ORIGIN_COOKIE_NAME,
|
|
874
|
+
getRequestOrigin,
|
|
875
|
+
setPublicOriginCookie,
|
|
876
|
+
clearPublicOriginCookie,
|
|
877
|
+
getStoredPublicOrigin,
|
|
878
|
+
isSecureRequest,
|
|
879
|
+
AUTH_REDIRECT_COOKIE_NAME,
|
|
880
|
+
getAuthRedirectTarget,
|
|
881
|
+
setAuthRedirectCookie,
|
|
882
|
+
clearAuthRedirectCookie,
|
|
883
|
+
getGlobalAdminEmails,
|
|
884
|
+
isGlobalAdminEmail,
|
|
885
|
+
createAuthIndexHtml,
|
|
886
|
+
AUTH_INDEX_HTML,
|
|
887
|
+
pkceCookiePrefix,
|
|
888
|
+
generateStateToken,
|
|
889
|
+
getPkceCookieName,
|
|
890
|
+
verifyState,
|
|
891
|
+
parseStateToken,
|
|
892
|
+
verifyStateToken,
|
|
893
|
+
encodeSessionToken,
|
|
894
|
+
decodeSessionToken,
|
|
895
|
+
getCasdoorConfig,
|
|
896
|
+
getCasdoorAuthorizeUrl,
|
|
897
|
+
getCasdoorTokenUrl,
|
|
898
|
+
getCasdoorUserInfoUrl,
|
|
899
|
+
exchangeCodeForToken,
|
|
900
|
+
fetchCasdoorUserInfo,
|
|
901
|
+
decodeCasdoorAccessToken,
|
|
902
|
+
exchangeCasdoorOAuthToken,
|
|
903
|
+
createLoginEntryResponse,
|
|
904
|
+
createSignupEntryResponse,
|
|
905
|
+
createAuthorizeEntryResponse,
|
|
906
|
+
createCallbackResponse,
|
|
907
|
+
createCallbackHandler
|
|
908
|
+
};
|
|
909
|
+
//# sourceMappingURL=chunk-IQEVUR77.js.map
|