@foldspace-fe/casdoor-next-auth-kit 0.1.23 → 0.1.24
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/auth-role-C35sP1i6.d.ts +40 -0
- package/dist/callback-Da3JC_EN.d.ts +18 -0
- package/dist/casdoor/index.d.ts +3 -8
- package/dist/casdoor/index.js +6 -4
- package/dist/{chunk-GLK4IW22.js → chunk-CSQFNYTS.js} +25 -11
- package/dist/chunk-CSQFNYTS.js.map +1 -0
- package/dist/{chunk-MWXY4JSL.js → chunk-IPJT66SK.js} +19 -11
- package/dist/{chunk-MWXY4JSL.js.map → chunk-IPJT66SK.js.map} +1 -1
- package/dist/chunk-JCQ5P7QZ.js +74 -0
- package/dist/chunk-JCQ5P7QZ.js.map +1 -0
- package/dist/chunk-YHPSOLXM.js +904 -0
- package/dist/chunk-YHPSOLXM.js.map +1 -0
- package/dist/cli-templates-IhA9gjyF.d.ts +31 -0
- package/dist/cli-templates.d.ts +2 -0
- package/dist/cli-templates.js +7 -0
- package/dist/cli-templates.js.map +1 -0
- package/dist/cli.js +52 -557
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -14
- package/dist/index.js +82 -32
- package/dist/next/index.d.ts +3 -3
- package/dist/next/index.js +7 -5
- package/dist/{options-D2YQdRWu.d.ts → options-CpWDszxZ.d.ts} +5 -2
- package/dist/react/index.d.ts +5 -4
- package/dist/react/index.js +4 -18
- package/dist/react/index.js.map +1 -1
- package/dist/skills/casdoor-next-auth-kit/SKILL.md +1 -0
- package/dist/{types-BJv6j3NZ.d.ts → types-COXcI8tx.d.ts} +3 -1
- package/package.json +1 -1
- package/dist/callback-rEWxVGyL.d.ts +0 -12
- package/dist/chunk-GLK4IW22.js.map +0 -1
- package/dist/chunk-SZVWLQQT.js +0 -332
- package/dist/chunk-SZVWLQQT.js.map +0 -1
- package/dist/chunk-T2M5MVPE.js +0 -20
- package/dist/chunk-T2M5MVPE.js.map +0 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { A as AuthUserRole, a as AuthUser } from './types-COXcI8tx.js';
|
|
2
|
+
|
|
3
|
+
type AuthSummaryRole = 'guest' | AuthUserRole;
|
|
4
|
+
interface AuthUserLike {
|
|
5
|
+
id?: string | null;
|
|
6
|
+
sub?: string | null;
|
|
7
|
+
name?: string | null;
|
|
8
|
+
displayName?: string | null;
|
|
9
|
+
email?: string | null;
|
|
10
|
+
image?: string | null;
|
|
11
|
+
picture?: string | null;
|
|
12
|
+
avatarUrl?: string | null;
|
|
13
|
+
isAdmin?: boolean;
|
|
14
|
+
role?: string | null;
|
|
15
|
+
tokenBalance?: number;
|
|
16
|
+
isVip?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface AuthUserSummaryShape {
|
|
19
|
+
id: string | null;
|
|
20
|
+
name: string;
|
|
21
|
+
email: string | null;
|
|
22
|
+
image: string | null;
|
|
23
|
+
isAuthenticated: boolean;
|
|
24
|
+
isAdmin: boolean;
|
|
25
|
+
tokenBalance: number;
|
|
26
|
+
isVip: boolean;
|
|
27
|
+
role: AuthSummaryRole;
|
|
28
|
+
}
|
|
29
|
+
declare function resolveAuthUserRole(role: string | null | undefined, isAdmin: boolean): AuthUserRole;
|
|
30
|
+
declare function buildAuthUserFromProfile(profile: AuthUserLike, isAdmin: boolean): AuthUser;
|
|
31
|
+
declare function buildAuthUserFromToken(token: AuthUserLike & {
|
|
32
|
+
userId?: string;
|
|
33
|
+
sub?: string;
|
|
34
|
+
id?: string;
|
|
35
|
+
accessToken?: string;
|
|
36
|
+
expiresAt?: number;
|
|
37
|
+
}, isAdmin: boolean): AuthUser;
|
|
38
|
+
declare function buildAuthUserSummary(user: AuthUserLike | null | undefined): AuthUserSummaryShape;
|
|
39
|
+
|
|
40
|
+
export { type AuthSummaryRole as A, type AuthUserLike as a, type AuthUserSummaryShape as b, buildAuthUserFromProfile as c, buildAuthUserFromToken as d, buildAuthUserSummary as e, resolveAuthUserRole as r };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { b as AuthKitConfig, O as OAuthTokens, C as CasdoorUserInfo, c as AuthBusinessAdapter, d as AuthPersistenceAdapter, a as AuthUser } from './types-COXcI8tx.js';
|
|
3
|
+
|
|
4
|
+
declare function exchangeCodeForToken(config: AuthKitConfig, code: string, redirectUri: string, codeVerifier: string): Promise<OAuthTokens>;
|
|
5
|
+
declare function fetchCasdoorUserInfo(config: AuthKitConfig, accessToken: string): Promise<CasdoorUserInfo>;
|
|
6
|
+
declare function decodeCasdoorAccessToken(accessToken: string): Record<string, unknown> | null;
|
|
7
|
+
declare const exchangeCasdoorOAuthToken: typeof exchangeCodeForToken;
|
|
8
|
+
|
|
9
|
+
interface CallbackHandlerOptions {
|
|
10
|
+
config: AuthKitConfig;
|
|
11
|
+
adapter?: AuthBusinessAdapter;
|
|
12
|
+
persistence?: AuthPersistenceAdapter;
|
|
13
|
+
}
|
|
14
|
+
declare function mapProfileToAuthUser(profile: Awaited<ReturnType<typeof fetchCasdoorUserInfo>>, adapter?: AuthBusinessAdapter): AuthUser;
|
|
15
|
+
declare function createCallbackResponse(request: NextRequest, options: CallbackHandlerOptions): Promise<NextResponse>;
|
|
16
|
+
declare function createCallbackHandler(options: CallbackHandlerOptions): (request: NextRequest) => Promise<NextResponse<unknown>>;
|
|
17
|
+
|
|
18
|
+
export { type CallbackHandlerOptions as C, createCallbackResponse as a, exchangeCodeForToken as b, createCallbackHandler as c, decodeCasdoorAccessToken as d, exchangeCasdoorOAuthToken as e, fetchCasdoorUserInfo as f, mapProfileToAuthUser as m };
|
package/dist/casdoor/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as AuthKitConfig } from '../types-COXcI8tx.js';
|
|
2
|
+
export { C as CallbackHandlerOptions, c as createCallbackHandler, a as createCallbackResponse, d as decodeCasdoorAccessToken, e as exchangeCasdoorOAuthToken, b as exchangeCodeForToken, f as fetchCasdoorUserInfo, m as mapProfileToAuthUser } from '../callback-Da3JC_EN.js';
|
|
2
3
|
import { NextRequest, NextResponse } from 'next/server';
|
|
3
|
-
export { C as CallbackHandlerOptions, c as createCallbackHandler, a as createCallbackResponse } from '../callback-rEWxVGyL.js';
|
|
4
4
|
|
|
5
5
|
declare function getCasdoorConfig(config: AuthKitConfig): AuthKitConfig;
|
|
6
6
|
declare function getCasdoorAuthorizeUrl(config: AuthKitConfig, params: {
|
|
@@ -12,11 +12,6 @@ declare function getCasdoorAuthorizeUrl(config: AuthKitConfig, params: {
|
|
|
12
12
|
declare function getCasdoorTokenUrl(config: AuthKitConfig): string;
|
|
13
13
|
declare function getCasdoorUserInfoUrl(config: AuthKitConfig): string;
|
|
14
14
|
|
|
15
|
-
declare function exchangeCodeForToken(config: AuthKitConfig, code: string, redirectUri: string, codeVerifier: string): Promise<OAuthTokens>;
|
|
16
|
-
declare function fetchCasdoorUserInfo(config: AuthKitConfig, accessToken: string): Promise<CasdoorUserInfo>;
|
|
17
|
-
declare function decodeCasdoorAccessToken(accessToken: string): Record<string, unknown> | null;
|
|
18
|
-
declare const exchangeCasdoorOAuthToken: typeof exchangeCodeForToken;
|
|
19
|
-
|
|
20
15
|
declare function createLoginEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse>;
|
|
21
16
|
declare function createSignupEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse>;
|
|
22
17
|
declare function createAuthorizeEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse>;
|
|
@@ -25,4 +20,4 @@ declare function createCasdoorApiProxyHandler(config: AuthKitConfig, prefix?: st
|
|
|
25
20
|
declare function createCasdoorPageProxyHandler(config: AuthKitConfig, prefix?: string, upstreamPrefix?: string): (request: NextRequest) => Promise<NextResponse>;
|
|
26
21
|
declare function createCasdoorCommerceProxyHandler(config: AuthKitConfig, prefix?: string, upstreamPrefix?: string): (request: NextRequest) => Promise<NextResponse>;
|
|
27
22
|
|
|
28
|
-
export { createAuthorizeEntryResponse, createCasdoorApiProxyHandler, createCasdoorCommerceProxyHandler, createCasdoorPageProxyHandler, createLoginEntryResponse, createSignupEntryResponse,
|
|
23
|
+
export { createAuthorizeEntryResponse, createCasdoorApiProxyHandler, createCasdoorCommerceProxyHandler, createCasdoorPageProxyHandler, createLoginEntryResponse, createSignupEntryResponse, getCasdoorAuthorizeUrl, getCasdoorConfig, getCasdoorTokenUrl, getCasdoorUserInfoUrl };
|
package/dist/casdoor/index.js
CHANGED
|
@@ -16,9 +16,10 @@ import {
|
|
|
16
16
|
getCasdoorAuthorizeUrl,
|
|
17
17
|
getCasdoorConfig,
|
|
18
18
|
getCasdoorTokenUrl,
|
|
19
|
-
getCasdoorUserInfoUrl
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
getCasdoorUserInfoUrl,
|
|
20
|
+
mapProfileToAuthUser
|
|
21
|
+
} from "../chunk-IPJT66SK.js";
|
|
22
|
+
import "../chunk-JCQ5P7QZ.js";
|
|
22
23
|
export {
|
|
23
24
|
createAuthorizeEntryResponse,
|
|
24
25
|
createCallbackHandler,
|
|
@@ -35,6 +36,7 @@ export {
|
|
|
35
36
|
getCasdoorAuthorizeUrl,
|
|
36
37
|
getCasdoorConfig,
|
|
37
38
|
getCasdoorTokenUrl,
|
|
38
|
-
getCasdoorUserInfoUrl
|
|
39
|
+
getCasdoorUserInfoUrl,
|
|
40
|
+
mapProfileToAuthUser
|
|
39
41
|
};
|
|
40
42
|
//# sourceMappingURL=index.js.map
|
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
isGlobalAdminEmail,
|
|
10
10
|
isSecureRequest,
|
|
11
11
|
normalizeAuthKitConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IPJT66SK.js";
|
|
13
|
+
import {
|
|
14
|
+
buildAuthUserFromToken
|
|
15
|
+
} from "./chunk-JCQ5P7QZ.js";
|
|
13
16
|
|
|
14
17
|
// src/next/login.ts
|
|
15
18
|
function createLoginRouteHandler(config) {
|
|
@@ -85,15 +88,22 @@ function createLogoutHandler(config) {
|
|
|
85
88
|
import NextAuth from "next-auth";
|
|
86
89
|
function resolveAuthUserFromToken(token, adapter) {
|
|
87
90
|
const email = typeof token.email === "string" ? token.email : null;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
const isAdmin = Boolean(token.isAdmin) || token.role === "admin" || Boolean(adapter?.isAdminEmail?.(email)) || isGlobalAdminEmail(email);
|
|
92
|
+
return buildAuthUserFromToken(
|
|
93
|
+
{
|
|
94
|
+
userId: token.userId,
|
|
95
|
+
sub: token.sub,
|
|
96
|
+
id: token.id,
|
|
97
|
+
name: token.name,
|
|
98
|
+
email,
|
|
99
|
+
picture: token.picture ?? null,
|
|
100
|
+
isAdmin: token.isAdmin,
|
|
101
|
+
role: token.role,
|
|
102
|
+
tokenBalance: token.tokenBalance,
|
|
103
|
+
isVip: token.isVip
|
|
104
|
+
},
|
|
105
|
+
isAdmin
|
|
106
|
+
);
|
|
97
107
|
}
|
|
98
108
|
function createNextAuthOptions(options) {
|
|
99
109
|
const normalized = normalizeAuthKitConfig(options.config);
|
|
@@ -124,6 +134,7 @@ function createNextAuthOptions(options) {
|
|
|
124
134
|
typedToken.email = typedProfile.email || typedToken.email;
|
|
125
135
|
typedToken.picture = typedProfile.image || typedProfile.picture || typedToken.picture;
|
|
126
136
|
typedToken.isAdmin = Boolean(typedProfile.isAdmin ?? typedToken.isAdmin);
|
|
137
|
+
typedToken.role = typedProfile.role === "admin" || typedProfile.role === "user" ? typedProfile.role : typedToken.role ?? (typedToken.isAdmin ? "admin" : "user");
|
|
127
138
|
typedToken.tokenBalance = typedProfile.tokenBalance ?? typedToken.tokenBalance ?? 2580;
|
|
128
139
|
typedToken.isVip = typedProfile.isVip ?? typedToken.isVip ?? true;
|
|
129
140
|
}
|
|
@@ -139,6 +150,7 @@ function createNextAuthOptions(options) {
|
|
|
139
150
|
if (typedSession.user) {
|
|
140
151
|
typedSession.user.id = resolvedUser.id;
|
|
141
152
|
typedSession.user.isAdmin = resolvedUser.isAdmin;
|
|
153
|
+
typedSession.user.role = resolvedUser.role;
|
|
142
154
|
typedSession.user.tokenBalance = resolvedUser.tokenBalance;
|
|
143
155
|
typedSession.user.isVip = resolvedUser.isVip;
|
|
144
156
|
}
|
|
@@ -151,6 +163,7 @@ function createNextAuthOptions(options) {
|
|
|
151
163
|
image: typedSession.user?.image || resolvedUser.image,
|
|
152
164
|
id: resolvedUser.id,
|
|
153
165
|
isAdmin: resolvedUser.isAdmin,
|
|
166
|
+
role: resolvedUser.role,
|
|
154
167
|
tokenBalance: resolvedUser.tokenBalance,
|
|
155
168
|
isVip: resolvedUser.isVip
|
|
156
169
|
};
|
|
@@ -190,7 +203,8 @@ export {
|
|
|
190
203
|
createSignupRouteHandler,
|
|
191
204
|
createAuthorizeRouteHandler,
|
|
192
205
|
createLogoutHandler,
|
|
206
|
+
resolveAuthUserFromToken,
|
|
193
207
|
createNextAuthOptions,
|
|
194
208
|
createNextAuthRouteHandler
|
|
195
209
|
};
|
|
196
|
-
//# sourceMappingURL=chunk-
|
|
210
|
+
//# sourceMappingURL=chunk-CSQFNYTS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/next/login.ts","../src/next/signup.ts","../src/next/authorize.ts","../src/next/logout.ts","../src/next/options.ts"],"sourcesContent":["import type { NextRequest } from 'next/server';\nimport type { AuthKitConfig } from '../types';\nimport { createLoginEntryResponse } from '../casdoor/entry';\n\nexport function createLoginRouteHandler(config: AuthKitConfig) {\n return async (request: NextRequest) => createLoginEntryResponse(request, config);\n}\n","import type { NextRequest } from 'next/server';\nimport type { AuthKitConfig } from '../types';\nimport { createSignupEntryResponse } from '../casdoor/entry';\n\nexport function createSignupRouteHandler(config: AuthKitConfig) {\n return async (request: NextRequest) => createSignupEntryResponse(request, config);\n}\n","import type { NextRequest } from 'next/server';\nimport type { AuthKitConfig } from '../types';\nimport { createAuthorizeEntryResponse } from '../casdoor/entry';\n\nexport function createAuthorizeRouteHandler(config: AuthKitConfig) {\n return async (request: NextRequest) => createAuthorizeEntryResponse(request, config);\n}\n","import { NextResponse, type NextRequest } from 'next/server';\nimport type { AuthKitConfig } from '../types';\nimport { isSecureRequest } from '../core/request-security';\nimport { clearAuthRedirectCookie } from '../core/auth-redirect';\nimport { clearPublicOriginCookie } from '../core/public-origin';\n\nfunction getCookieNamesFromHeader(cookieHeader: string | null): string[] {\n if (!cookieHeader) {\n return [];\n }\n\n return cookieHeader\n .split(';')\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => part.split('=')[0]?.trim())\n .filter((name): name is string => Boolean(name));\n}\n\nfunction getPathCandidates(pathname: string): string[] {\n const normalized = pathname.startsWith('/') ? pathname : `/${pathname}`;\n const segments = normalized.split('/').filter(Boolean);\n const paths = new Set<string>(['/']);\n\n let current = '';\n for (const segment of segments) {\n current += `/${segment}`;\n paths.add(current);\n }\n\n return [...paths];\n}\n\nfunction resolveLogoutTargetUrl(request: NextRequest, config: AuthKitConfig): URL {\n const origin = request.cookies.get('auth_origin')?.value ?? config.appUrl ?? new URL(request.url).origin;\n const logoutRedirectPath = config.logoutRedirectPath ?? '/';\n return new URL(logoutRedirectPath, origin);\n}\n\nfunction clearCookieEverywhere(\n response: NextResponse,\n cookieName: string,\n secure: boolean,\n pathCandidates: string[],\n) {\n for (const path of pathCandidates) {\n response.cookies.set(cookieName, '', {\n path,\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n }\n}\n\nexport function createLogoutHandler(config: AuthKitConfig) {\n return async function GET(request: NextRequest) {\n const secure = config.cookie?.secure === 'auto' ? isSecureRequest(request, config.appUrl) : Boolean(config.cookie?.secure);\n // 307 keeps same-path targets behaving like a reload instead of a cache-friendly rewrite.\n const targetUrl = resolveLogoutTargetUrl(request, config);\n const response = NextResponse.redirect(targetUrl, 307);\n response.headers.set('Clear-Site-Data', '\"cookies\"');\n const cookieNames = getCookieNamesFromHeader(request.headers.get('cookie'));\n const pathCandidates = getPathCandidates(request.nextUrl.pathname);\n\n for (const cookieName of cookieNames) {\n clearCookieEverywhere(response, cookieName, secure, pathCandidates);\n }\n clearCookieEverywhere(response, 'oauth_state', secure, pathCandidates);\n clearCookieEverywhere(response, 'auth_origin', secure, pathCandidates);\n clearCookieEverywhere(response, 'auth_redirect', secure, pathCandidates);\n clearAuthRedirectCookie(response, secure);\n clearPublicOriginCookie(response, secure);\n\n return response;\n };\n}\n","import NextAuth from 'next-auth';\nimport type { NextAuthOptions, Session } from 'next-auth';\nimport type { JWT } from 'next-auth/jwt';\nimport type { AuthBusinessAdapter, AuthKitConfig, AuthPersistenceAdapter, AuthUser, AuthUserRole } from '../types';\nimport { normalizeAuthKitConfig } from '../core/config';\nimport { decodeSessionToken, encodeSessionToken } from '../core/session-token';\nimport { isGlobalAdminEmail } from '../core/admin';\nimport { buildAuthUserFromToken } from '../core/auth-role';\n\nexport interface NextAuthRouteOptions {\n config: AuthKitConfig;\n adapter?: AuthBusinessAdapter;\n persistence?: AuthPersistenceAdapter;\n providers?: NextAuthOptions['providers'];\n}\n\nexport interface AuthTokenPayload extends JWT {\n id?: string;\n name?: string;\n email?: string;\n picture?: string | null;\n userId?: string;\n accessToken?: string;\n expiresAt?: number;\n tokenBalance?: number;\n isVip?: boolean;\n isAdmin?: boolean;\n role?: AuthUserRole;\n}\n\nexport interface AuthSessionUser {\n id?: string;\n isAdmin?: boolean;\n role?: AuthUserRole;\n tokenBalance?: number;\n isVip?: boolean;\n}\n\nexport interface AuthSession extends Session {\n accessToken?: string;\n expiresAt?: number;\n user?: AuthSessionUser & NonNullable<Session['user']>;\n}\n\nexport function resolveAuthUserFromToken(token: AuthTokenPayload, adapter?: AuthBusinessAdapter): AuthUser {\n const email = typeof token.email === 'string' ? token.email : null;\n const isAdmin = Boolean(token.isAdmin) || token.role === 'admin' || Boolean(adapter?.isAdminEmail?.(email)) || isGlobalAdminEmail(email);\n\n return buildAuthUserFromToken(\n {\n userId: token.userId,\n sub: token.sub,\n id: token.id,\n name: token.name,\n email,\n picture: token.picture ?? null,\n isAdmin: token.isAdmin,\n role: token.role,\n tokenBalance: token.tokenBalance,\n isVip: token.isVip,\n },\n isAdmin,\n );\n}\n\nexport function createNextAuthOptions(options: NextAuthRouteOptions): NextAuthOptions {\n const normalized = normalizeAuthKitConfig(options.config);\n\n return {\n providers: options.providers ?? [],\n session: {\n strategy: 'jwt',\n },\n jwt: {\n encode: encodeSessionToken,\n decode: decodeSessionToken,\n },\n pages: {\n signIn: '/login',\n error: '/callback/error',\n },\n callbacks: {\n async jwt({ token, account, profile }) {\n const typedToken = token as AuthTokenPayload;\n\n if (account) {\n typedToken.accessToken = account.access_token;\n typedToken.expiresAt = account.expires_at ? account.expires_at * 1000 : undefined;\n }\n\n if (profile && typeof profile === 'object') {\n const typedProfile = profile as Partial<AuthUser> & {\n sub?: string;\n id?: string;\n picture?: string;\n };\n\n typedToken.userId = typedProfile.id || typedProfile.sub || typedToken.userId;\n typedToken.name = typedProfile.name || typedToken.name;\n typedToken.email = typedProfile.email || typedToken.email;\n typedToken.picture = typedProfile.image || typedProfile.picture || typedToken.picture;\n typedToken.isAdmin = Boolean(typedProfile.isAdmin ?? typedToken.isAdmin);\n typedToken.role =\n typedProfile.role === 'admin' || typedProfile.role === 'user'\n ? typedProfile.role\n : typedToken.role ?? (typedToken.isAdmin ? 'admin' : 'user');\n typedToken.tokenBalance = typedProfile.tokenBalance ?? typedToken.tokenBalance ?? 2580;\n typedToken.isVip = typedProfile.isVip ?? typedToken.isVip ?? true;\n }\n\n return typedToken;\n },\n async session({ session, token }) {\n const typedSession = session as AuthSession;\n const typedToken = token as AuthTokenPayload;\n const tokenUserId = typedToken.userId || typedToken.sub || typedToken.id || '';\n const tokenEmail = typeof typedToken.email === 'string' ? typedToken.email : null;\n const persistedUser = options.persistence?.findAuthUser\n ? await options.persistence.findAuthUser({ id: tokenUserId || undefined, email: tokenEmail })\n : null;\n const resolvedUser = persistedUser ?? resolveAuthUserFromToken(typedToken, options.adapter);\n\n if (typedSession.user) {\n typedSession.user.id = resolvedUser.id;\n typedSession.user.isAdmin = resolvedUser.isAdmin;\n typedSession.user.role = resolvedUser.role;\n typedSession.user.tokenBalance = resolvedUser.tokenBalance;\n typedSession.user.isVip = resolvedUser.isVip;\n }\n\n typedSession.accessToken = typedToken.accessToken;\n typedSession.expiresAt = typedToken.expiresAt;\n typedSession.user = {\n ...(typedSession.user || {}),\n name: typedSession.user?.name || resolvedUser.name,\n email: typedSession.user?.email || resolvedUser.email,\n image: typedSession.user?.image || resolvedUser.image,\n id: resolvedUser.id,\n isAdmin: resolvedUser.isAdmin,\n role: resolvedUser.role,\n tokenBalance: resolvedUser.tokenBalance,\n isVip: resolvedUser.isVip,\n };\n\n return typedSession;\n },\n },\n events: {\n async signOut({ token }) {\n const typedToken = token as AuthTokenPayload | null;\n if (!typedToken?.accessToken || !normalized.appUrl) {\n return;\n }\n\n try {\n await fetch(new URL('/api/casdoor/logout', normalized.appUrl).toString(), {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${typedToken.accessToken}`,\n },\n });\n } catch {\n // ignored\n }\n },\n },\n secret: normalized.nextauthSecret,\n };\n}\n\nexport function createNextAuthRouteHandler(options: NextAuthRouteOptions) {\n const handler = NextAuth(createNextAuthOptions(options));\n return {\n GET: handler,\n POST: handler,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
buildAuthUserFromProfile,
|
|
2
3
|
resolvePostLoginRedirect
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JCQ5P7QZ.js";
|
|
4
5
|
|
|
5
6
|
// src/core/config.ts
|
|
6
7
|
function normalizeAuthKitConfig(config) {
|
|
@@ -735,15 +736,20 @@ function mapProfileToAuthUser(profile, adapter) {
|
|
|
735
736
|
const typedProfile = profile;
|
|
736
737
|
const email = typedProfile.email || null;
|
|
737
738
|
const isAdmin = Boolean(typedProfile.isAdmin) || Boolean(adapter?.isAdminEmail?.(email)) || isGlobalAdminEmail(email);
|
|
738
|
-
return
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
739
|
+
return buildAuthUserFromProfile(
|
|
740
|
+
{
|
|
741
|
+
id: typedProfile.id,
|
|
742
|
+
sub: typedProfile.sub,
|
|
743
|
+
name: typedProfile.name,
|
|
744
|
+
displayName: typedProfile.displayName,
|
|
745
|
+
email,
|
|
746
|
+
picture: typedProfile.picture,
|
|
747
|
+
avatarUrl: typedProfile.avatarUrl,
|
|
748
|
+
isAdmin: typedProfile.isAdmin,
|
|
749
|
+
role: typedProfile.role
|
|
750
|
+
},
|
|
751
|
+
isAdmin
|
|
752
|
+
);
|
|
747
753
|
}
|
|
748
754
|
function getRedirectTarget(request, user, adapter) {
|
|
749
755
|
const adapterRedirect = adapter?.resolvePostLoginRedirect?.(user);
|
|
@@ -836,6 +842,7 @@ async function createCallbackResponse(request, options) {
|
|
|
836
842
|
accessToken,
|
|
837
843
|
expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : decodedAccessToken?.exp,
|
|
838
844
|
isAdmin: mappedUser.isAdmin,
|
|
845
|
+
role: mappedUser.role,
|
|
839
846
|
tokenBalance: mappedUser.tokenBalance,
|
|
840
847
|
isVip: mappedUser.isVip
|
|
841
848
|
},
|
|
@@ -903,7 +910,8 @@ export {
|
|
|
903
910
|
createLoginEntryResponse,
|
|
904
911
|
createSignupEntryResponse,
|
|
905
912
|
createAuthorizeEntryResponse,
|
|
913
|
+
mapProfileToAuthUser,
|
|
906
914
|
createCallbackResponse,
|
|
907
915
|
createCallbackHandler
|
|
908
916
|
};
|
|
909
|
-
//# sourceMappingURL=chunk-
|
|
917
|
+
//# sourceMappingURL=chunk-IPJT66SK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/config.ts","../src/core/public-origin.ts","../src/core/request-security.ts","../src/core/auth-redirect.ts","../src/core/admin.ts","../src/core/index-html.ts","../src/core/oauth-state.ts","../src/core/session-token.ts","../src/casdoor/config.ts","../src/casdoor/oauth.ts","../src/casdoor/entry.ts","../src/core/pkce.ts","../src/casdoor/callback.ts"],"sourcesContent":["import type { AuthKitConfig } from '../types';\n\nexport function normalizeAuthKitConfig(config: AuthKitConfig): AuthKitConfig {\n return {\n ...config,\n casdoor: {\n redirectPath: '/callback',\n signinPath: '/login/oauth/authorize',\n ...config.casdoor\n },\n cookie: {\n secure: 'auto',\n ...config.cookie\n },\n session: {\n maxAgeSeconds: 60 * 60 * 24 * 7,\n ...config.session\n }\n };\n}\n","export const PUBLIC_ORIGIN_COOKIE_NAME = 'auth_origin';\n\nexport function getRequestOrigin(request: Request, appUrl?: string): string {\n if (appUrl) {\n try {\n return new URL(appUrl).origin;\n } catch {\n // ignore and fall back to request headers\n }\n }\n\n const referer = request.headers.get('referer');\n if (referer) {\n try {\n return new URL(referer).origin;\n } catch {\n // ignore\n }\n }\n\n const origin = request.headers.get('origin');\n if (origin) {\n try {\n return new URL(origin).origin;\n } catch {\n // ignore\n }\n }\n\n const forwardedProto = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\n const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\n if (forwardedProto && forwardedHost) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n\n return new URL(request.url).origin;\n}\n\nexport function setPublicOriginCookie(response: { cookies: { set: (...args: any[]) => void } }, origin: string, secure: boolean) {\n response.cookies.set(PUBLIC_ORIGIN_COOKIE_NAME, origin, {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n });\n}\n\nexport function clearPublicOriginCookie(response: { cookies: { set: (...args: any[]) => void } }, secure: boolean) {\n response.cookies.set(PUBLIC_ORIGIN_COOKIE_NAME, '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n}\n\nexport function getStoredPublicOrigin(request: Request): string | null {\n const cookieHeader = request.headers.get('cookie');\n if (!cookieHeader) {\n return null;\n }\n\n for (const entry of cookieHeader.split(';')) {\n const [rawName, ...valueParts] = entry.trim().split('=');\n if (rawName === PUBLIC_ORIGIN_COOKIE_NAME) {\n const value = valueParts.join('=').trim();\n if (!value) {\n return null;\n }\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n }\n }\n\n return null;\n}\n","export function isSecureRequest(request: Request, appUrl?: string): boolean {\n const url = new URL(request.url);\n if (url.protocol === 'https:') return true;\n\n const forwardedProto = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim().toLowerCase();\n if (forwardedProto === 'https') return true;\n\n if (appUrl) {\n try {\n return new URL(appUrl).protocol === 'https:';\n } catch {\n return false;\n }\n }\n\n return false;\n}\n","export const AUTH_REDIRECT_COOKIE_NAME = 'auth_redirect';\n\nexport function getAuthRedirectTarget(request: Request): string | null {\n const cookieHeader = request.headers.get('cookie');\n if (!cookieHeader) {\n return null;\n }\n\n for (const entry of cookieHeader.split(';')) {\n const [rawName, ...valueParts] = entry.trim().split('=');\n if (rawName === AUTH_REDIRECT_COOKIE_NAME) {\n const value = valueParts.join('=').trim();\n if (!value) {\n return null;\n }\n let decoded = value;\n try {\n decoded = decodeURIComponent(value);\n } catch {\n // ignore\n }\n if (decoded.startsWith('/') && !decoded.startsWith('//')) {\n return decoded;\n }\n return null;\n }\n }\n\n return null;\n}\n\nexport function setAuthRedirectCookie(\n response: { cookies: { set: (...args: any[]) => void } },\n target: string,\n secure: boolean,\n) {\n response.cookies.set(AUTH_REDIRECT_COOKIE_NAME, target, {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n });\n}\n\nexport function clearAuthRedirectCookie(\n response: { cookies: { set: (...args: any[]) => void } },\n secure: boolean,\n) {\n response.cookies.set(AUTH_REDIRECT_COOKIE_NAME, '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n}\n","const DEFAULT_ADMIN_EMAILS = ['admin@example.com'];\n\nfunction readAdminEmailSource(): string {\n return process.env.GLOBAL_ADMIN_EMAILS || process.env.ADMIN_EMAILS || '';\n}\n\nexport function getGlobalAdminEmails(): string[] {\n const source = readAdminEmailSource();\n if (!source) {\n return DEFAULT_ADMIN_EMAILS;\n }\n\n return source\n .split(',')\n .map((value) => value.trim().toLowerCase())\n .filter(Boolean);\n}\n\nexport function isGlobalAdminEmail(email: string | null | undefined): boolean {\n if (!email) {\n return false;\n }\n\n return getGlobalAdminEmails().includes(email.toLowerCase());\n}\n","import type { AuthIndexHtmlOptions } from '../types';\n\nconst DEFAULT_CASDOOR_STATIC_ORIGIN = 'https://casdoor-static.foldspace.cn';\nconst DEFAULT_CASDOOR_ORIGIN = process.env.NEXT_PUBLIC_CASDOOR_SERVER_URL || 'https://auth.heyaai.com';\n\nconst DEFAULT_ICON_HREF = 'https://cdn.casbin.org/img/favicon.png';\nconst DEFAULT_MANIFEST_HREF = '/manifest.json';\n\nfunction escapeHtmlAttribute(value: string): string {\n return value.replaceAll('&', '&').replaceAll('\"', '"').replaceAll('<', '<').replaceAll('>', '>');\n}\n\nexport function createAuthIndexHtml(options: AuthIndexHtmlOptions = {}): string {\n const staticOrigin = options.staticOrigin || DEFAULT_CASDOOR_STATIC_ORIGIN;\n const casdoorOrigin = options.casdoorOrigin || DEFAULT_CASDOOR_ORIGIN;\n const apiProxyPrefix = options.apiProxyPrefix || '/auth/';\n const appName = options.appName || '创小剧 AI';\n const organizationName = options.organizationName || 'built-in';\n const description = options.description || '创小剧 AI 登录 - 一个支持 OAuth 2.0、OIDC、SAML 和 CAS 的身份与单点登录平台';\n const iconHref = options.iconHref || DEFAULT_ICON_HREF;\n const manifestHref = options.manifestHref || DEFAULT_MANIFEST_HREF;\n const mainJs = `${staticOrigin}/static/js/main.5ddbc6ff.js`;\n const mainCss = `${staticOrigin}/static/css/main.f35879a1.css`;\n\n return String.raw`<!doctype html>\n<html lang=\"zh-CN\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta name=\"description\" content=\"${escapeHtmlAttribute(description)}\" />\n <link rel=\"apple-touch-icon\" href=\"${escapeHtmlAttribute(iconHref)}\" />\n <link rel=\"manifest\" href=\"${escapeHtmlAttribute(manifestHref)}\" />\n <title>${escapeHtmlAttribute(appName)}</title>\n <script>\n (function () {\n var cdnOrigin = ${JSON.stringify(staticOrigin)}\n var casdoorOrigin = ${JSON.stringify(casdoorOrigin)}\n var currentOrigin = window.location.origin\n var proxyPrefix = ${JSON.stringify(apiProxyPrefix)}\n var proxyPathPrefix = proxyPrefix.replace(/\\/$/, '')\n var applicationId = ${JSON.stringify((options.organizationName || 'built-in') + '/' + (options.appName || '创小剧 AI'))}\n\n function toProxyUrl(input) {\n try {\n var url = typeof input === 'string' ? new URL(input, window.location.href) : input instanceof URL ? input : null\n if (!url) {\n return input\n }\n\n if (url.origin === cdnOrigin && url.pathname.indexOf(proxyPrefix) === 0) {\n return currentOrigin + url.pathname + url.search + url.hash\n }\n\n if (url.origin === currentOrigin && url.pathname.indexOf('/static/') === 0) {\n return cdnOrigin + url.pathname + url.search + url.hash\n }\n\n if (url.origin === currentOrigin && (url.pathname === '/auth' || url.pathname.indexOf('/auth/') === 0)) {\n if (url.pathname === '/auth/api/get-application') {\n url.searchParams.set('id', applicationId)\n }\n return currentOrigin + proxyPathPrefix + url.pathname.slice('/auth'.length) + url.search + url.hash\n }\n\n if (url.origin === casdoorOrigin) {\n return currentOrigin + proxyPathPrefix + url.pathname + url.search + url.hash\n }\n } catch (error) {\n return input\n }\n\n return input\n }\n\n function rewriteElement(element) {\n if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n return\n }\n\n if (element.tagName === 'A' && element.getAttribute('href')) {\n var href = element.getAttribute('href')\n var rewrittenHref = toProxyUrl(href)\n if (rewrittenHref !== href) {\n element.setAttribute('href', rewrittenHref)\n }\n }\n\n if (element.tagName === 'FORM' && element.getAttribute('action')) {\n var action = element.getAttribute('action')\n var rewrittenAction = toProxyUrl(action)\n if (rewrittenAction !== action) {\n element.setAttribute('action', rewrittenAction)\n }\n }\n\n if (element.tagName === 'SCRIPT' && element.getAttribute('src')) {\n var scriptSrc = element.getAttribute('src')\n var rewrittenScriptSrc = toProxyUrl(scriptSrc)\n if (rewrittenScriptSrc !== scriptSrc) {\n element.setAttribute('src', rewrittenScriptSrc)\n }\n }\n\n if (element.tagName === 'LINK' && element.getAttribute('href')) {\n var linkHref = element.getAttribute('href')\n var rewrittenLinkHref = toProxyUrl(linkHref)\n if (rewrittenLinkHref !== linkHref) {\n element.setAttribute('href', rewrittenLinkHref)\n }\n }\n\n if (element.tagName === 'IMG' && element.getAttribute('src')) {\n var imgSrc = element.getAttribute('src')\n var rewrittenImgSrc = toProxyUrl(imgSrc)\n if (rewrittenImgSrc !== imgSrc) {\n element.setAttribute('src', rewrittenImgSrc)\n }\n }\n\n if (typeof element.querySelectorAll === 'function') {\n element.querySelectorAll('a[href], form[action], script[src], link[href], img[src]').forEach(rewriteElement)\n }\n }\n\n if (typeof window.fetch === 'function') {\n var originalFetch = window.fetch.bind(window)\n window.fetch = function (input, init) {\n return originalFetch(toProxyUrl(input), init)\n }\n }\n\n if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) {\n var originalOpen = window.XMLHttpRequest.prototype.open\n window.XMLHttpRequest.prototype.open = function (method, url) {\n var rewrittenUrl = toProxyUrl(url)\n return originalOpen.apply(this, [method, rewrittenUrl].concat(Array.prototype.slice.call(arguments, 2)))\n }\n }\n\n if (window.open) {\n var originalOpenWindow = window.open.bind(window)\n window.open = function (url) {\n return originalOpenWindow(toProxyUrl(url), arguments[1], arguments[2])\n }\n }\n\n if (window.location && typeof window.location.assign === 'function') {\n var originalAssign = window.location.assign.bind(window.location)\n window.location.assign = function (url) {\n return originalAssign(toProxyUrl(url))\n }\n }\n\n if (window.location && typeof window.location.replace === 'function') {\n var originalReplace = window.location.replace.bind(window.location)\n window.location.replace = function (url) {\n return originalReplace(toProxyUrl(url))\n }\n }\n\n if (window.HTMLFormElement && window.HTMLFormElement.prototype) {\n var originalSubmit = window.HTMLFormElement.prototype.submit\n window.HTMLFormElement.prototype.submit = function () {\n if (this.action) {\n this.action = toProxyUrl(this.action)\n }\n return originalSubmit.apply(this, arguments)\n }\n }\n\n document.addEventListener('click', function (event) {\n var target = event.target instanceof Element ? event.target.closest('a[href]') : null\n if (!target) {\n return\n }\n\n var href = target.getAttribute('href')\n var rewritten = toProxyUrl(href)\n if (rewritten !== href) {\n event.preventDefault()\n window.location.href = rewritten\n }\n }, true)\n\n document.addEventListener('submit', function (event) {\n var form = event.target instanceof HTMLFormElement ? event.target : null\n if (!form || !form.action) {\n return\n }\n\n var rewritten = toProxyUrl(form.action)\n if (rewritten !== form.action) {\n event.preventDefault()\n form.action = rewritten\n form.submit()\n }\n }, true)\n\n var originalAppendChild = Node.prototype.appendChild\n Node.prototype.appendChild = function (node) {\n rewriteElement(node)\n return originalAppendChild.call(this, node)\n }\n\n var originalInsertBefore = Node.prototype.insertBefore\n Node.prototype.insertBefore = function (node, referenceNode) {\n rewriteElement(node)\n return originalInsertBefore.call(this, node, referenceNode)\n }\n\n if (document.body) {\n rewriteElement(document.body)\n }\n\n if (window.MutationObserver) {\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(rewriteElement)\n })\n })\n observer.observe(document.documentElement, { childList: true, subtree: true })\n }\n })()\n </script>\n <script defer=\"defer\" src=\"${escapeHtmlAttribute(mainJs)}\"></script>\n <link href=\"${escapeHtmlAttribute(mainCss)}\" rel=\"stylesheet\" />\n </head>\n <body>\n <noscript>你需要启用 JavaScript 才能继续。</noscript>\n <div id=\"root\"></div>\n </body>\n</html>\n`;\n}\n\nexport const AUTH_INDEX_HTML = createAuthIndexHtml();\n","import { Buffer } from 'node:buffer';\nimport crypto from 'node:crypto';\n\nconst STATE_EXPIRY_SECONDS = 600;\nconst STATE_SECRET =\n process.env.NEXTAUTH_SECRET || process.env.CASDOOR_CLIENT_SECRET || 'dev-state-secret';\n\nexport const pkceCookiePrefix = 'pkce_code_verifier';\n\nexport interface StatePayload {\n nonce: string;\n issuedAt: number;\n}\n\nfunction signStatePayload(payload: StatePayload): string {\n const body = Buffer.from(JSON.stringify(payload)).toString('base64url');\n const signature = crypto.createHmac('sha256', STATE_SECRET).update(body).digest('base64url');\n return `${body}.${signature}`;\n}\n\nfunction decodeStatePayload(state: string): StatePayload | null {\n const [body, signature] = state.split('.');\n\n if (!body || !signature) {\n return null;\n }\n\n const expectedSignature = crypto.createHmac('sha256', STATE_SECRET).update(body).digest('base64url');\n\n if (\n expectedSignature.length !== signature.length ||\n !crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(signature))\n ) {\n return null;\n }\n\n try {\n return JSON.parse(Buffer.from(body, 'base64url').toString('utf8')) as StatePayload;\n } catch {\n return null;\n }\n}\n\nexport function generateStateToken(): string {\n return signStatePayload({\n nonce: crypto.randomUUID(),\n issuedAt: Date.now(),\n });\n}\n\nexport function getPkceCookieName(state: string): string {\n const digest = crypto.createHash('sha256').update(state).digest('base64url');\n return `${pkceCookiePrefix}.${digest}`;\n}\n\nexport async function verifyState(stateFromUrl: string): Promise<boolean> {\n const payload = decodeStatePayload(stateFromUrl);\n if (!payload) {\n return false;\n }\n\n return Date.now() - payload.issuedAt <= STATE_EXPIRY_SECONDS * 1000;\n}\n\nexport function parseStateToken(token: string | null | undefined): StatePayload | null {\n if (!token) return null;\n return decodeStatePayload(token);\n}\n\nexport function verifyStateToken(token: string | null | undefined): boolean {\n if (!token) return false;\n return Boolean(decodeStatePayload(token));\n}\n","import { Buffer } from 'node:buffer';\nimport crypto from 'node:crypto';\nimport type { JWT, JWTDecodeParams, JWTEncodeParams } from 'next-auth/jwt';\n\nconst DEFAULT_MAX_AGE = 30 * 24 * 60 * 60;\n\nfunction base64UrlEncode(value: string): string {\n return Buffer.from(value, 'utf8').toString('base64url');\n}\n\nfunction base64UrlDecode(value: string): string {\n return Buffer.from(value, 'base64url').toString('utf8');\n}\n\nfunction createSignature(input: string, secret: string | Buffer): string {\n return crypto.createHmac('sha256', secret).update(input).digest('base64url');\n}\n\nfunction timingSafeEqual(left: string, right: string): boolean {\n const leftBuffer = Buffer.from(left);\n const rightBuffer = Buffer.from(right);\n\n if (leftBuffer.length !== rightBuffer.length) {\n return false;\n }\n\n return crypto.timingSafeEqual(leftBuffer, rightBuffer);\n}\n\nexport async function encodeSessionToken(params: JWTEncodeParams): Promise<string> {\n const { token = {}, secret, maxAge = DEFAULT_MAX_AGE } = params;\n const issuedAt = Math.floor(Date.now() / 1000);\n const header = base64UrlEncode(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));\n const payload = base64UrlEncode(\n JSON.stringify({\n ...token,\n iat: issuedAt,\n exp: issuedAt + maxAge,\n jti: crypto.randomUUID(),\n }),\n );\n const signature = createSignature(`${header}.${payload}`, secret);\n\n return `${header}.${payload}.${signature}`;\n}\n\nexport async function decodeSessionToken(params: JWTDecodeParams): Promise<JWT | null> {\n const { token, secret } = params;\n\n if (!token) {\n return null;\n }\n\n const [header, payload, signature] = token.split('.');\n\n if (!header || !payload || !signature) {\n return null;\n }\n\n const expectedSignature = createSignature(`${header}.${payload}`, secret);\n\n if (!timingSafeEqual(signature, expectedSignature)) {\n return null;\n }\n\n try {\n const parsedPayload = JSON.parse(base64UrlDecode(payload)) as JWT & { exp?: number };\n\n if (parsedPayload.exp && parsedPayload.exp <= Math.floor(Date.now() / 1000)) {\n return null;\n }\n\n return parsedPayload;\n } catch {\n return null;\n }\n}\n","import type { AuthKitConfig } from '../types';\nimport { normalizeAuthKitConfig } from '../core/config';\n\nexport function getCasdoorConfig(config: AuthKitConfig): AuthKitConfig {\n return normalizeAuthKitConfig(config);\n}\n\nexport function getCasdoorAuthorizeUrl(config: AuthKitConfig, params: { state: string; codeChallenge: string; redirectUri: string; kind: 'login' | 'signup' }): string {\n const base = new URL(config.casdoor.signinPath ?? '/login/oauth/authorize', config.casdoor.serverUrl);\n base.searchParams.set('response_type', 'code');\n base.searchParams.set('client_id', config.casdoor.clientId);\n base.searchParams.set('redirect_uri', params.redirectUri);\n base.searchParams.set('scope', 'profile');\n base.searchParams.set('state', params.state);\n base.searchParams.set('code_challenge', params.codeChallenge);\n base.searchParams.set('code_challenge_method', 'S256');\n if (params.kind === 'signup') {\n base.searchParams.set('action', 'signup');\n }\n return base.toString();\n}\n\nexport function getCasdoorTokenUrl(config: AuthKitConfig): string {\n return new URL('/api/login/oauth/access_token', config.casdoor.serverUrl).toString();\n}\n\nexport function getCasdoorUserInfoUrl(config: AuthKitConfig): string {\n return new URL('/api/userinfo', config.casdoor.serverUrl).toString();\n}\n","import type { AuthKitConfig, CasdoorUserInfo, OAuthTokens } from '../types';\nimport { getCasdoorTokenUrl, getCasdoorUserInfoUrl } from './config';\nimport { Buffer } from 'node:buffer';\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> | null {\n const parts = token.split('.');\n if (parts.length < 2) {\n return null;\n }\n\n try {\n const payload = parts[1];\n return JSON.parse(Buffer.from(payload, 'base64url').toString('utf8')) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport async function exchangeCodeForToken(config: AuthKitConfig, code: string, redirectUri: string, codeVerifier: string): Promise<OAuthTokens> {\n const response = await fetch(getCasdoorTokenUrl(config), {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'authorization_code',\n client_id: config.casdoor.clientId,\n client_secret: config.casdoor.clientSecret,\n code,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier\n })\n });\n if (!response.ok) {\n throw new Error('Failed to exchange Casdoor authorization code.');\n }\n return (await response.json()) as OAuthTokens;\n}\n\nexport async function fetchCasdoorUserInfo(config: AuthKitConfig, accessToken: string): Promise<CasdoorUserInfo> {\n const response = await fetch(getCasdoorUserInfoUrl(config), {\n headers: {\n authorization: 'Bearer ' + accessToken\n }\n });\n if (!response.ok) {\n throw new Error('Failed to fetch Casdoor user profile.');\n }\n return (await response.json()) as CasdoorUserInfo;\n}\n\nexport function decodeCasdoorAccessToken(accessToken: string): Record<string, unknown> | null {\n return decodeJwtPayload(accessToken);\n}\n\nexport const exchangeCasdoorOAuthToken = exchangeCodeForToken;\n","import { NextResponse, type NextRequest } from 'next/server';\nimport type { AuthKitConfig } from '../types';\nimport { normalizeAuthKitConfig } from '../core/config';\nimport { getRequestOrigin, setPublicOriginCookie } from '../core/public-origin';\nimport { isSecureRequest } from '../core/request-security';\nimport { createPkcePair } from '../core/pkce';\nimport { generateStateToken, getPkceCookieName } from '../core/oauth-state';\nimport { getAuthRedirectTarget, setAuthRedirectCookie } from '../core/auth-redirect';\nimport { createAuthIndexHtml } from '../core/index-html';\n\nfunction buildLocalAuthorizeUrl(\n origin: string,\n config: AuthKitConfig,\n params: { state: string; codeChallenge: string; kind: 'login' | 'signup' },\n): string {\n const normalized = normalizeAuthKitConfig(config);\n const authorizePath =\n params.kind === 'signup'\n ? '/signup/oauth/authorize'\n : normalized.casdoor.signinPath || '/login/oauth/authorize';\n const authorizeUrl = new URL(authorizePath, origin);\n authorizeUrl.searchParams.set('response_type', 'code');\n authorizeUrl.searchParams.set('client_id', normalized.casdoor.clientId);\n authorizeUrl.searchParams.set('redirect_uri', `${origin}${normalized.casdoor.redirectPath || '/callback'}`);\n authorizeUrl.searchParams.set('scope', 'profile');\n authorizeUrl.searchParams.set('state', params.state);\n authorizeUrl.searchParams.set('code_challenge', params.codeChallenge);\n authorizeUrl.searchParams.set('code_challenge_method', 'S256');\n return authorizeUrl.toString();\n}\n\nasync function createRedirectEntryResponse(\n request: NextRequest,\n config: AuthKitConfig,\n kind: 'login' | 'signup',\n): Promise<NextResponse> {\n const normalized = normalizeAuthKitConfig(config);\n const origin = getRequestOrigin(request, normalized.appUrl);\n const secure =\n normalized.cookie?.secure === 'auto' ? isSecureRequest(request, normalized.appUrl) : Boolean(normalized.cookie?.secure);\n const { verifier, challenge } = await createPkcePair();\n const state = generateStateToken();\n const response = NextResponse.redirect(\n buildLocalAuthorizeUrl(origin, normalized, { state, codeChallenge: challenge, kind }),\n 307,\n );\n const redirectTarget = getAuthRedirectTarget(request);\n if (redirectTarget) {\n setAuthRedirectCookie(response, redirectTarget, secure);\n }\n setPublicOriginCookie(response, origin, secure);\n response.cookies.set('oauth_state', state, { httpOnly: true, sameSite: 'lax', secure, path: '/' });\n response.cookies.set(getPkceCookieName(state), verifier, { httpOnly: true, sameSite: 'lax', secure, path: '/' });\n return response;\n}\n\nasync function createAuthorizePageResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n const normalized = normalizeAuthKitConfig(config);\n const origin = getRequestOrigin(request, normalized.appUrl);\n const secure =\n normalized.cookie?.secure === 'auto' ? isSecureRequest(request, normalized.appUrl) : Boolean(normalized.cookie?.secure);\n const response = new NextResponse(\n createAuthIndexHtml({\n appName: normalized.casdoor.appName,\n organizationName: normalized.casdoor.organizationName,\n staticOrigin: process.env.NEXT_PUBLIC_CASDOOR_STATIC_ORIGIN,\n casdoorOrigin: normalized.casdoor.serverUrl,\n apiProxyPrefix: '/auth/',\n }),\n {\n status: 200,\n headers: {\n 'content-type': 'text/html; charset=utf-8',\n 'cache-control': 'no-store, max-age=0',\n },\n },\n );\n setPublicOriginCookie(response, origin, secure);\n return response;\n}\n\nexport async function createLoginEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n return createRedirectEntryResponse(request, config, 'login');\n}\n\nexport async function createSignupEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n return createRedirectEntryResponse(request, config, 'signup');\n}\n\nexport async function createAuthorizeEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n return createAuthorizePageResponse(request, config);\n}\n","const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\n\nfunction toBase64Url(bytes: ArrayBuffer): string {\n const raw = Buffer.from(bytes).toString('base64');\n return raw.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '');\n}\n\nexport async function createPkcePair(): Promise<{ verifier: string; challenge: string }> {\n const bytes = crypto.getRandomValues(new Uint8Array(48));\n const verifier = Array.from(bytes, (byte) => chars[byte % chars.length]).join('');\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n return { verifier, challenge: toBase64Url(digest) };\n}\n","import { NextResponse, type NextRequest } from 'next/server';\nimport type { AuthBusinessAdapter, AuthKitConfig, AuthPersistenceAdapter, AuthUser } from '../types';\nimport { normalizeAuthKitConfig } from '../core/config';\nimport { getRequestOrigin, getStoredPublicOrigin, clearPublicOriginCookie } from '../core/public-origin';\nimport { isSecureRequest } from '../core/request-security';\nimport { getAuthRedirectTarget, clearAuthRedirectCookie } from '../core/auth-redirect';\nimport {\n decodeCasdoorAccessToken,\n exchangeCasdoorOAuthToken,\n fetchCasdoorUserInfo,\n} from './oauth';\nimport { getCasdoorConfig } from './config';\nimport { getPkceCookieName, verifyState } from '../core/oauth-state';\nimport { encodeSessionToken } from '../core/session-token';\nimport { isGlobalAdminEmail } from '../core/admin';\nimport { resolvePostLoginRedirect } from '../core/redirect';\n\nexport interface CallbackHandlerOptions {\n config: AuthKitConfig;\n adapter?: AuthBusinessAdapter;\n persistence?: AuthPersistenceAdapter;\n}\n\nfunction readCookieHeaderValue(cookieHeader: string | null, name: string): string | null {\n if (!cookieHeader) {\n return null;\n }\n\n for (const entry of cookieHeader.split(';')) {\n const [rawName, ...valueParts] = entry.trim().split('=');\n if (rawName === name) {\n const value = valueParts.join('=').trim();\n return value || null;\n }\n }\n\n return null;\n}\n\nfunction getPublicOrigin(request: NextRequest, config: AuthKitConfig): string {\n return getStoredPublicOrigin(request) || getRequestOrigin(request, config.appUrl);\n}\n\nfunction rewriteToCallbackErrorPage(\n request: NextRequest,\n config: AuthKitConfig,\n title: string,\n message: string,\n details?: string,\n): NextResponse {\n const origin = getPublicOrigin(request, config);\n const targetUrl = new URL('/callback/error', origin);\n targetUrl.searchParams.set('title', title);\n targetUrl.searchParams.set('message', message);\n\n if (details) {\n targetUrl.searchParams.set('details', details);\n }\n\n return NextResponse.redirect(targetUrl, 307);\n}\n\nfunction getPkceCodeVerifier(request: NextRequest, state: string): string | null {\n return readCookieHeaderValue(request.headers.get('cookie'), getPkceCookieName(state));\n}\n\nfunction setNextAuthSessionCookies(response: NextResponse, sessionToken: string, isSecure: boolean): void {\n const cookieName = isSecure ? '__Secure-next-auth.session-token' : 'next-auth.session-token';\n const expires = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);\n const baseOptions = {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n secure: isSecure,\n expires,\n };\n const maxCookieSize = 3933;\n\n if (sessionToken.length <= maxCookieSize) {\n response.cookies.set(cookieName, sessionToken, baseOptions);\n return;\n }\n\n const chunkCount = Math.ceil(sessionToken.length / maxCookieSize);\n for (let index = 0; index < chunkCount; index++) {\n response.cookies.set(\n `${cookieName}.${index}`,\n sessionToken.slice(index * maxCookieSize, (index + 1) * maxCookieSize),\n baseOptions,\n );\n }\n}\n\nfunction sanitizeRedirectPath(value: string | null): string {\n if (!value || !value.startsWith('/') || value.startsWith('//')) {\n return '/user/account';\n }\n\n return value;\n}\n\nfunction summarizeCookieHeader(cookieHeader: string | null): Record<string, unknown> {\n if (!cookieHeader) {\n return { present: false };\n }\n\n const cookieNames = cookieHeader\n .split(';')\n .map((entry) => entry.trim().split('=')[0])\n .filter(Boolean);\n\n return {\n present: true,\n count: cookieNames.length,\n names: cookieNames,\n };\n}\n\nfunction mapProfileToAuthUser(profile: Awaited<ReturnType<typeof fetchCasdoorUserInfo>>, adapter?: AuthBusinessAdapter): AuthUser {\n const typedProfile = profile as Awaited<ReturnType<typeof fetchCasdoorUserInfo>> & {\n sub?: string;\n picture?: string;\n avatarUrl?: string;\n };\n const email = typedProfile.email || null;\n const isAdmin =\n Boolean(typedProfile.isAdmin) ||\n Boolean(adapter?.isAdminEmail?.(email)) ||\n isGlobalAdminEmail(email);\n\n return {\n id: typedProfile.sub || typedProfile.id || typedProfile.email || 'casdoor-user',\n name: typedProfile.name || typedProfile.displayName || null,\n email,\n image: typedProfile.picture || typedProfile.avatarUrl || null,\n isAdmin,\n tokenBalance: 2580,\n isVip: true,\n };\n}\n\nfunction getRedirectTarget(request: NextRequest, user: AuthUser, adapter?: AuthBusinessAdapter): string {\n const adapterRedirect = adapter?.resolvePostLoginRedirect?.(user);\n if (adapterRedirect) {\n return sanitizeRedirectPath(adapterRedirect);\n }\n\n const storedRedirect = getAuthRedirectTarget(request);\n if (storedRedirect) {\n return sanitizeRedirectPath(storedRedirect);\n }\n\n return sanitizeRedirectPath(resolvePostLoginRedirect(user, '/user/account'));\n}\n\nexport async function createCallbackResponse(\n request: NextRequest,\n options: CallbackHandlerOptions,\n): Promise<NextResponse> {\n const normalized = normalizeAuthKitConfig(options.config);\n const publicOrigin = getPublicOrigin(request, normalized);\n const url = new URL(request.url);\n const code = url.searchParams.get('code');\n const state = url.searchParams.get('state');\n const error = url.searchParams.get('error');\n const secure = normalized.cookie?.secure === 'auto'\n ? isSecureRequest(request, normalized.appUrl)\n : Boolean(normalized.cookie?.secure);\n\n if (error) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n 'Casdoor 返回了授权错误',\n '授权服务器在回调阶段返回了错误信息。请返回首页或重新登录后再试。',\n error,\n );\n }\n\n if (!code) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '缺少授权码',\n 'Casdoor 回调没有带回 code,这通常意味着授权流程未完成。',\n 'no_code',\n );\n }\n\n if (!state || !(await verifyState(state))) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '登录状态校验失败',\n '回调中的 state 与本次登录流程不匹配,请重新发起登录。',\n 'invalid_state',\n );\n }\n\n const codeVerifier = getPkceCodeVerifier(request, state);\n if (!codeVerifier) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '缺少 PKCE 校验值',\n '回调请求里没有找到 pkce_code_verifier cookie。请重新从登录入口发起流程。',\n 'missing_pkce_code_verifier',\n );\n }\n\n const casdoorConfig = getCasdoorConfig(normalized);\n const redirectUri = `${publicOrigin}${casdoorConfig.casdoor.redirectPath}`;\n const tokens = await exchangeCasdoorOAuthToken(casdoorConfig, code, redirectUri, codeVerifier);\n const accessToken = tokens.access_token ?? tokens.accessToken ?? '';\n\n if (!accessToken) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '缺少访问令牌',\n 'Casdoor 回调没有返回 access token。',\n 'missing_access_token',\n );\n }\n\n const profile = await fetchCasdoorUserInfo(casdoorConfig, accessToken);\n\n const decodedAccessToken = decodeCasdoorAccessToken(accessToken) as { exp?: number } | null;\n const mappedUser = options.adapter?.onUserSync\n ? await options.adapter.onUserSync(profile, {\n accessToken,\n refreshToken: tokens.refresh_token || tokens.refreshToken,\n idToken: tokens.id_token || tokens.idToken,\n expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1000 : tokens.expiresAt,\n })\n : mapProfileToAuthUser(profile, options.adapter);\n\n if (options.persistence?.syncAuthUser) {\n await options.persistence.syncAuthUser(mappedUser);\n }\n\n const sessionToken = await encodeSessionToken({\n token: {\n id: mappedUser.id,\n sub: mappedUser.id,\n userId: mappedUser.id,\n name: mappedUser.name,\n email: mappedUser.email,\n picture: mappedUser.image,\n accessToken,\n expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1000 : decodedAccessToken?.exp,\n isAdmin: mappedUser.isAdmin,\n tokenBalance: mappedUser.tokenBalance,\n isVip: mappedUser.isVip,\n },\n secret: normalized.nextauthSecret,\n maxAge: normalized.session?.maxAgeSeconds,\n });\n\n const response = NextResponse.redirect(new URL(getRedirectTarget(request, mappedUser, options.adapter), publicOrigin));\n setNextAuthSessionCookies(response, sessionToken, secure);\n response.cookies.set(getPkceCookieName(state), '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n response.cookies.set('oauth_state', '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n clearAuthRedirectCookie(response, secure);\n clearPublicOriginCookie(response, secure);\n return response;\n}\n\nexport function createCallbackHandler(options: CallbackHandlerOptions) {\n return async function GET(request: NextRequest) {\n return createCallbackResponse(request, options);\n };\n}\n"],"mappings":"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","names":["Buffer","crypto","Buffer","crypto","Buffer","NextResponse","NextResponse","NextResponse"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/config.ts","../src/core/public-origin.ts","../src/core/request-security.ts","../src/core/auth-redirect.ts","../src/core/admin.ts","../src/core/index-html.ts","../src/core/oauth-state.ts","../src/core/session-token.ts","../src/casdoor/config.ts","../src/casdoor/oauth.ts","../src/casdoor/entry.ts","../src/core/pkce.ts","../src/casdoor/callback.ts"],"sourcesContent":["import type { AuthKitConfig } from '../types';\n\nexport function normalizeAuthKitConfig(config: AuthKitConfig): AuthKitConfig {\n return {\n ...config,\n casdoor: {\n redirectPath: '/callback',\n signinPath: '/login/oauth/authorize',\n ...config.casdoor\n },\n cookie: {\n secure: 'auto',\n ...config.cookie\n },\n session: {\n maxAgeSeconds: 60 * 60 * 24 * 7,\n ...config.session\n }\n };\n}\n","export const PUBLIC_ORIGIN_COOKIE_NAME = 'auth_origin';\n\nexport function getRequestOrigin(request: Request, appUrl?: string): string {\n if (appUrl) {\n try {\n return new URL(appUrl).origin;\n } catch {\n // ignore and fall back to request headers\n }\n }\n\n const referer = request.headers.get('referer');\n if (referer) {\n try {\n return new URL(referer).origin;\n } catch {\n // ignore\n }\n }\n\n const origin = request.headers.get('origin');\n if (origin) {\n try {\n return new URL(origin).origin;\n } catch {\n // ignore\n }\n }\n\n const forwardedProto = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\n const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\n if (forwardedProto && forwardedHost) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n\n return new URL(request.url).origin;\n}\n\nexport function setPublicOriginCookie(response: { cookies: { set: (...args: any[]) => void } }, origin: string, secure: boolean) {\n response.cookies.set(PUBLIC_ORIGIN_COOKIE_NAME, origin, {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n });\n}\n\nexport function clearPublicOriginCookie(response: { cookies: { set: (...args: any[]) => void } }, secure: boolean) {\n response.cookies.set(PUBLIC_ORIGIN_COOKIE_NAME, '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n}\n\nexport function getStoredPublicOrigin(request: Request): string | null {\n const cookieHeader = request.headers.get('cookie');\n if (!cookieHeader) {\n return null;\n }\n\n for (const entry of cookieHeader.split(';')) {\n const [rawName, ...valueParts] = entry.trim().split('=');\n if (rawName === PUBLIC_ORIGIN_COOKIE_NAME) {\n const value = valueParts.join('=').trim();\n if (!value) {\n return null;\n }\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n }\n }\n\n return null;\n}\n","export function isSecureRequest(request: Request, appUrl?: string): boolean {\n const url = new URL(request.url);\n if (url.protocol === 'https:') return true;\n\n const forwardedProto = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim().toLowerCase();\n if (forwardedProto === 'https') return true;\n\n if (appUrl) {\n try {\n return new URL(appUrl).protocol === 'https:';\n } catch {\n return false;\n }\n }\n\n return false;\n}\n","export const AUTH_REDIRECT_COOKIE_NAME = 'auth_redirect';\n\nexport function getAuthRedirectTarget(request: Request): string | null {\n const cookieHeader = request.headers.get('cookie');\n if (!cookieHeader) {\n return null;\n }\n\n for (const entry of cookieHeader.split(';')) {\n const [rawName, ...valueParts] = entry.trim().split('=');\n if (rawName === AUTH_REDIRECT_COOKIE_NAME) {\n const value = valueParts.join('=').trim();\n if (!value) {\n return null;\n }\n let decoded = value;\n try {\n decoded = decodeURIComponent(value);\n } catch {\n // ignore\n }\n if (decoded.startsWith('/') && !decoded.startsWith('//')) {\n return decoded;\n }\n return null;\n }\n }\n\n return null;\n}\n\nexport function setAuthRedirectCookie(\n response: { cookies: { set: (...args: any[]) => void } },\n target: string,\n secure: boolean,\n) {\n response.cookies.set(AUTH_REDIRECT_COOKIE_NAME, target, {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n });\n}\n\nexport function clearAuthRedirectCookie(\n response: { cookies: { set: (...args: any[]) => void } },\n secure: boolean,\n) {\n response.cookies.set(AUTH_REDIRECT_COOKIE_NAME, '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n}\n","const DEFAULT_ADMIN_EMAILS = ['admin@example.com'];\n\nfunction readAdminEmailSource(): string {\n return process.env.GLOBAL_ADMIN_EMAILS || process.env.ADMIN_EMAILS || '';\n}\n\nexport function getGlobalAdminEmails(): string[] {\n const source = readAdminEmailSource();\n if (!source) {\n return DEFAULT_ADMIN_EMAILS;\n }\n\n return source\n .split(',')\n .map((value) => value.trim().toLowerCase())\n .filter(Boolean);\n}\n\nexport function isGlobalAdminEmail(email: string | null | undefined): boolean {\n if (!email) {\n return false;\n }\n\n return getGlobalAdminEmails().includes(email.toLowerCase());\n}\n","import type { AuthIndexHtmlOptions } from '../types';\n\nconst DEFAULT_CASDOOR_STATIC_ORIGIN = 'https://casdoor-static.foldspace.cn';\nconst DEFAULT_CASDOOR_ORIGIN = process.env.NEXT_PUBLIC_CASDOOR_SERVER_URL || 'https://auth.heyaai.com';\n\nconst DEFAULT_ICON_HREF = 'https://cdn.casbin.org/img/favicon.png';\nconst DEFAULT_MANIFEST_HREF = '/manifest.json';\n\nfunction escapeHtmlAttribute(value: string): string {\n return value.replaceAll('&', '&').replaceAll('\"', '"').replaceAll('<', '<').replaceAll('>', '>');\n}\n\nexport function createAuthIndexHtml(options: AuthIndexHtmlOptions = {}): string {\n const staticOrigin = options.staticOrigin || DEFAULT_CASDOOR_STATIC_ORIGIN;\n const casdoorOrigin = options.casdoorOrigin || DEFAULT_CASDOOR_ORIGIN;\n const apiProxyPrefix = options.apiProxyPrefix || '/auth/';\n const appName = options.appName || '创小剧 AI';\n const organizationName = options.organizationName || 'built-in';\n const description = options.description || '创小剧 AI 登录 - 一个支持 OAuth 2.0、OIDC、SAML 和 CAS 的身份与单点登录平台';\n const iconHref = options.iconHref || DEFAULT_ICON_HREF;\n const manifestHref = options.manifestHref || DEFAULT_MANIFEST_HREF;\n const mainJs = `${staticOrigin}/static/js/main.5ddbc6ff.js`;\n const mainCss = `${staticOrigin}/static/css/main.f35879a1.css`;\n\n return String.raw`<!doctype html>\n<html lang=\"zh-CN\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta name=\"description\" content=\"${escapeHtmlAttribute(description)}\" />\n <link rel=\"apple-touch-icon\" href=\"${escapeHtmlAttribute(iconHref)}\" />\n <link rel=\"manifest\" href=\"${escapeHtmlAttribute(manifestHref)}\" />\n <title>${escapeHtmlAttribute(appName)}</title>\n <script>\n (function () {\n var cdnOrigin = ${JSON.stringify(staticOrigin)}\n var casdoorOrigin = ${JSON.stringify(casdoorOrigin)}\n var currentOrigin = window.location.origin\n var proxyPrefix = ${JSON.stringify(apiProxyPrefix)}\n var proxyPathPrefix = proxyPrefix.replace(/\\/$/, '')\n var applicationId = ${JSON.stringify((options.organizationName || 'built-in') + '/' + (options.appName || '创小剧 AI'))}\n\n function toProxyUrl(input) {\n try {\n var url = typeof input === 'string' ? new URL(input, window.location.href) : input instanceof URL ? input : null\n if (!url) {\n return input\n }\n\n if (url.origin === cdnOrigin && url.pathname.indexOf(proxyPrefix) === 0) {\n return currentOrigin + url.pathname + url.search + url.hash\n }\n\n if (url.origin === currentOrigin && url.pathname.indexOf('/static/') === 0) {\n return cdnOrigin + url.pathname + url.search + url.hash\n }\n\n if (url.origin === currentOrigin && (url.pathname === '/auth' || url.pathname.indexOf('/auth/') === 0)) {\n if (url.pathname === '/auth/api/get-application') {\n url.searchParams.set('id', applicationId)\n }\n return currentOrigin + proxyPathPrefix + url.pathname.slice('/auth'.length) + url.search + url.hash\n }\n\n if (url.origin === casdoorOrigin) {\n return currentOrigin + proxyPathPrefix + url.pathname + url.search + url.hash\n }\n } catch (error) {\n return input\n }\n\n return input\n }\n\n function rewriteElement(element) {\n if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n return\n }\n\n if (element.tagName === 'A' && element.getAttribute('href')) {\n var href = element.getAttribute('href')\n var rewrittenHref = toProxyUrl(href)\n if (rewrittenHref !== href) {\n element.setAttribute('href', rewrittenHref)\n }\n }\n\n if (element.tagName === 'FORM' && element.getAttribute('action')) {\n var action = element.getAttribute('action')\n var rewrittenAction = toProxyUrl(action)\n if (rewrittenAction !== action) {\n element.setAttribute('action', rewrittenAction)\n }\n }\n\n if (element.tagName === 'SCRIPT' && element.getAttribute('src')) {\n var scriptSrc = element.getAttribute('src')\n var rewrittenScriptSrc = toProxyUrl(scriptSrc)\n if (rewrittenScriptSrc !== scriptSrc) {\n element.setAttribute('src', rewrittenScriptSrc)\n }\n }\n\n if (element.tagName === 'LINK' && element.getAttribute('href')) {\n var linkHref = element.getAttribute('href')\n var rewrittenLinkHref = toProxyUrl(linkHref)\n if (rewrittenLinkHref !== linkHref) {\n element.setAttribute('href', rewrittenLinkHref)\n }\n }\n\n if (element.tagName === 'IMG' && element.getAttribute('src')) {\n var imgSrc = element.getAttribute('src')\n var rewrittenImgSrc = toProxyUrl(imgSrc)\n if (rewrittenImgSrc !== imgSrc) {\n element.setAttribute('src', rewrittenImgSrc)\n }\n }\n\n if (typeof element.querySelectorAll === 'function') {\n element.querySelectorAll('a[href], form[action], script[src], link[href], img[src]').forEach(rewriteElement)\n }\n }\n\n if (typeof window.fetch === 'function') {\n var originalFetch = window.fetch.bind(window)\n window.fetch = function (input, init) {\n return originalFetch(toProxyUrl(input), init)\n }\n }\n\n if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) {\n var originalOpen = window.XMLHttpRequest.prototype.open\n window.XMLHttpRequest.prototype.open = function (method, url) {\n var rewrittenUrl = toProxyUrl(url)\n return originalOpen.apply(this, [method, rewrittenUrl].concat(Array.prototype.slice.call(arguments, 2)))\n }\n }\n\n if (window.open) {\n var originalOpenWindow = window.open.bind(window)\n window.open = function (url) {\n return originalOpenWindow(toProxyUrl(url), arguments[1], arguments[2])\n }\n }\n\n if (window.location && typeof window.location.assign === 'function') {\n var originalAssign = window.location.assign.bind(window.location)\n window.location.assign = function (url) {\n return originalAssign(toProxyUrl(url))\n }\n }\n\n if (window.location && typeof window.location.replace === 'function') {\n var originalReplace = window.location.replace.bind(window.location)\n window.location.replace = function (url) {\n return originalReplace(toProxyUrl(url))\n }\n }\n\n if (window.HTMLFormElement && window.HTMLFormElement.prototype) {\n var originalSubmit = window.HTMLFormElement.prototype.submit\n window.HTMLFormElement.prototype.submit = function () {\n if (this.action) {\n this.action = toProxyUrl(this.action)\n }\n return originalSubmit.apply(this, arguments)\n }\n }\n\n document.addEventListener('click', function (event) {\n var target = event.target instanceof Element ? event.target.closest('a[href]') : null\n if (!target) {\n return\n }\n\n var href = target.getAttribute('href')\n var rewritten = toProxyUrl(href)\n if (rewritten !== href) {\n event.preventDefault()\n window.location.href = rewritten\n }\n }, true)\n\n document.addEventListener('submit', function (event) {\n var form = event.target instanceof HTMLFormElement ? event.target : null\n if (!form || !form.action) {\n return\n }\n\n var rewritten = toProxyUrl(form.action)\n if (rewritten !== form.action) {\n event.preventDefault()\n form.action = rewritten\n form.submit()\n }\n }, true)\n\n var originalAppendChild = Node.prototype.appendChild\n Node.prototype.appendChild = function (node) {\n rewriteElement(node)\n return originalAppendChild.call(this, node)\n }\n\n var originalInsertBefore = Node.prototype.insertBefore\n Node.prototype.insertBefore = function (node, referenceNode) {\n rewriteElement(node)\n return originalInsertBefore.call(this, node, referenceNode)\n }\n\n if (document.body) {\n rewriteElement(document.body)\n }\n\n if (window.MutationObserver) {\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n mutation.addedNodes.forEach(rewriteElement)\n })\n })\n observer.observe(document.documentElement, { childList: true, subtree: true })\n }\n })()\n </script>\n <script defer=\"defer\" src=\"${escapeHtmlAttribute(mainJs)}\"></script>\n <link href=\"${escapeHtmlAttribute(mainCss)}\" rel=\"stylesheet\" />\n </head>\n <body>\n <noscript>你需要启用 JavaScript 才能继续。</noscript>\n <div id=\"root\"></div>\n </body>\n</html>\n`;\n}\n\nexport const AUTH_INDEX_HTML = createAuthIndexHtml();\n","import { Buffer } from 'node:buffer';\nimport crypto from 'node:crypto';\n\nconst STATE_EXPIRY_SECONDS = 600;\nconst STATE_SECRET =\n process.env.NEXTAUTH_SECRET || process.env.CASDOOR_CLIENT_SECRET || 'dev-state-secret';\n\nexport const pkceCookiePrefix = 'pkce_code_verifier';\n\nexport interface StatePayload {\n nonce: string;\n issuedAt: number;\n}\n\nfunction signStatePayload(payload: StatePayload): string {\n const body = Buffer.from(JSON.stringify(payload)).toString('base64url');\n const signature = crypto.createHmac('sha256', STATE_SECRET).update(body).digest('base64url');\n return `${body}.${signature}`;\n}\n\nfunction decodeStatePayload(state: string): StatePayload | null {\n const [body, signature] = state.split('.');\n\n if (!body || !signature) {\n return null;\n }\n\n const expectedSignature = crypto.createHmac('sha256', STATE_SECRET).update(body).digest('base64url');\n\n if (\n expectedSignature.length !== signature.length ||\n !crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(signature))\n ) {\n return null;\n }\n\n try {\n return JSON.parse(Buffer.from(body, 'base64url').toString('utf8')) as StatePayload;\n } catch {\n return null;\n }\n}\n\nexport function generateStateToken(): string {\n return signStatePayload({\n nonce: crypto.randomUUID(),\n issuedAt: Date.now(),\n });\n}\n\nexport function getPkceCookieName(state: string): string {\n const digest = crypto.createHash('sha256').update(state).digest('base64url');\n return `${pkceCookiePrefix}.${digest}`;\n}\n\nexport async function verifyState(stateFromUrl: string): Promise<boolean> {\n const payload = decodeStatePayload(stateFromUrl);\n if (!payload) {\n return false;\n }\n\n return Date.now() - payload.issuedAt <= STATE_EXPIRY_SECONDS * 1000;\n}\n\nexport function parseStateToken(token: string | null | undefined): StatePayload | null {\n if (!token) return null;\n return decodeStatePayload(token);\n}\n\nexport function verifyStateToken(token: string | null | undefined): boolean {\n if (!token) return false;\n return Boolean(decodeStatePayload(token));\n}\n","import { Buffer } from 'node:buffer';\nimport crypto from 'node:crypto';\nimport type { JWT, JWTDecodeParams, JWTEncodeParams } from 'next-auth/jwt';\n\nconst DEFAULT_MAX_AGE = 30 * 24 * 60 * 60;\n\nfunction base64UrlEncode(value: string): string {\n return Buffer.from(value, 'utf8').toString('base64url');\n}\n\nfunction base64UrlDecode(value: string): string {\n return Buffer.from(value, 'base64url').toString('utf8');\n}\n\nfunction createSignature(input: string, secret: string | Buffer): string {\n return crypto.createHmac('sha256', secret).update(input).digest('base64url');\n}\n\nfunction timingSafeEqual(left: string, right: string): boolean {\n const leftBuffer = Buffer.from(left);\n const rightBuffer = Buffer.from(right);\n\n if (leftBuffer.length !== rightBuffer.length) {\n return false;\n }\n\n return crypto.timingSafeEqual(leftBuffer, rightBuffer);\n}\n\nexport async function encodeSessionToken(params: JWTEncodeParams): Promise<string> {\n const { token = {}, secret, maxAge = DEFAULT_MAX_AGE } = params;\n const issuedAt = Math.floor(Date.now() / 1000);\n const header = base64UrlEncode(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));\n const payload = base64UrlEncode(\n JSON.stringify({\n ...token,\n iat: issuedAt,\n exp: issuedAt + maxAge,\n jti: crypto.randomUUID(),\n }),\n );\n const signature = createSignature(`${header}.${payload}`, secret);\n\n return `${header}.${payload}.${signature}`;\n}\n\nexport async function decodeSessionToken(params: JWTDecodeParams): Promise<JWT | null> {\n const { token, secret } = params;\n\n if (!token) {\n return null;\n }\n\n const [header, payload, signature] = token.split('.');\n\n if (!header || !payload || !signature) {\n return null;\n }\n\n const expectedSignature = createSignature(`${header}.${payload}`, secret);\n\n if (!timingSafeEqual(signature, expectedSignature)) {\n return null;\n }\n\n try {\n const parsedPayload = JSON.parse(base64UrlDecode(payload)) as JWT & { exp?: number };\n\n if (parsedPayload.exp && parsedPayload.exp <= Math.floor(Date.now() / 1000)) {\n return null;\n }\n\n return parsedPayload;\n } catch {\n return null;\n }\n}\n","import type { AuthKitConfig } from '../types';\nimport { normalizeAuthKitConfig } from '../core/config';\n\nexport function getCasdoorConfig(config: AuthKitConfig): AuthKitConfig {\n return normalizeAuthKitConfig(config);\n}\n\nexport function getCasdoorAuthorizeUrl(config: AuthKitConfig, params: { state: string; codeChallenge: string; redirectUri: string; kind: 'login' | 'signup' }): string {\n const base = new URL(config.casdoor.signinPath ?? '/login/oauth/authorize', config.casdoor.serverUrl);\n base.searchParams.set('response_type', 'code');\n base.searchParams.set('client_id', config.casdoor.clientId);\n base.searchParams.set('redirect_uri', params.redirectUri);\n base.searchParams.set('scope', 'profile');\n base.searchParams.set('state', params.state);\n base.searchParams.set('code_challenge', params.codeChallenge);\n base.searchParams.set('code_challenge_method', 'S256');\n if (params.kind === 'signup') {\n base.searchParams.set('action', 'signup');\n }\n return base.toString();\n}\n\nexport function getCasdoorTokenUrl(config: AuthKitConfig): string {\n return new URL('/api/login/oauth/access_token', config.casdoor.serverUrl).toString();\n}\n\nexport function getCasdoorUserInfoUrl(config: AuthKitConfig): string {\n return new URL('/api/userinfo', config.casdoor.serverUrl).toString();\n}\n","import type { AuthKitConfig, CasdoorUserInfo, OAuthTokens } from '../types';\nimport { getCasdoorTokenUrl, getCasdoorUserInfoUrl } from './config';\nimport { Buffer } from 'node:buffer';\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> | null {\n const parts = token.split('.');\n if (parts.length < 2) {\n return null;\n }\n\n try {\n const payload = parts[1];\n return JSON.parse(Buffer.from(payload, 'base64url').toString('utf8')) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport async function exchangeCodeForToken(config: AuthKitConfig, code: string, redirectUri: string, codeVerifier: string): Promise<OAuthTokens> {\n const response = await fetch(getCasdoorTokenUrl(config), {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'authorization_code',\n client_id: config.casdoor.clientId,\n client_secret: config.casdoor.clientSecret,\n code,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier\n })\n });\n if (!response.ok) {\n throw new Error('Failed to exchange Casdoor authorization code.');\n }\n return (await response.json()) as OAuthTokens;\n}\n\nexport async function fetchCasdoorUserInfo(config: AuthKitConfig, accessToken: string): Promise<CasdoorUserInfo> {\n const response = await fetch(getCasdoorUserInfoUrl(config), {\n headers: {\n authorization: 'Bearer ' + accessToken\n }\n });\n if (!response.ok) {\n throw new Error('Failed to fetch Casdoor user profile.');\n }\n return (await response.json()) as CasdoorUserInfo;\n}\n\nexport function decodeCasdoorAccessToken(accessToken: string): Record<string, unknown> | null {\n return decodeJwtPayload(accessToken);\n}\n\nexport const exchangeCasdoorOAuthToken = exchangeCodeForToken;\n","import { NextResponse, type NextRequest } from 'next/server';\nimport type { AuthKitConfig } from '../types';\nimport { normalizeAuthKitConfig } from '../core/config';\nimport { getRequestOrigin, setPublicOriginCookie } from '../core/public-origin';\nimport { isSecureRequest } from '../core/request-security';\nimport { createPkcePair } from '../core/pkce';\nimport { generateStateToken, getPkceCookieName } from '../core/oauth-state';\nimport { getAuthRedirectTarget, setAuthRedirectCookie } from '../core/auth-redirect';\nimport { createAuthIndexHtml } from '../core/index-html';\n\nfunction buildLocalAuthorizeUrl(\n origin: string,\n config: AuthKitConfig,\n params: { state: string; codeChallenge: string; kind: 'login' | 'signup' },\n): string {\n const normalized = normalizeAuthKitConfig(config);\n const authorizePath =\n params.kind === 'signup'\n ? '/signup/oauth/authorize'\n : normalized.casdoor.signinPath || '/login/oauth/authorize';\n const authorizeUrl = new URL(authorizePath, origin);\n authorizeUrl.searchParams.set('response_type', 'code');\n authorizeUrl.searchParams.set('client_id', normalized.casdoor.clientId);\n authorizeUrl.searchParams.set('redirect_uri', `${origin}${normalized.casdoor.redirectPath || '/callback'}`);\n authorizeUrl.searchParams.set('scope', 'profile');\n authorizeUrl.searchParams.set('state', params.state);\n authorizeUrl.searchParams.set('code_challenge', params.codeChallenge);\n authorizeUrl.searchParams.set('code_challenge_method', 'S256');\n return authorizeUrl.toString();\n}\n\nasync function createRedirectEntryResponse(\n request: NextRequest,\n config: AuthKitConfig,\n kind: 'login' | 'signup',\n): Promise<NextResponse> {\n const normalized = normalizeAuthKitConfig(config);\n const origin = getRequestOrigin(request, normalized.appUrl);\n const secure =\n normalized.cookie?.secure === 'auto' ? isSecureRequest(request, normalized.appUrl) : Boolean(normalized.cookie?.secure);\n const { verifier, challenge } = await createPkcePair();\n const state = generateStateToken();\n const response = NextResponse.redirect(\n buildLocalAuthorizeUrl(origin, normalized, { state, codeChallenge: challenge, kind }),\n 307,\n );\n const redirectTarget = getAuthRedirectTarget(request);\n if (redirectTarget) {\n setAuthRedirectCookie(response, redirectTarget, secure);\n }\n setPublicOriginCookie(response, origin, secure);\n response.cookies.set('oauth_state', state, { httpOnly: true, sameSite: 'lax', secure, path: '/' });\n response.cookies.set(getPkceCookieName(state), verifier, { httpOnly: true, sameSite: 'lax', secure, path: '/' });\n return response;\n}\n\nasync function createAuthorizePageResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n const normalized = normalizeAuthKitConfig(config);\n const origin = getRequestOrigin(request, normalized.appUrl);\n const secure =\n normalized.cookie?.secure === 'auto' ? isSecureRequest(request, normalized.appUrl) : Boolean(normalized.cookie?.secure);\n const response = new NextResponse(\n createAuthIndexHtml({\n appName: normalized.casdoor.appName,\n organizationName: normalized.casdoor.organizationName,\n staticOrigin: process.env.NEXT_PUBLIC_CASDOOR_STATIC_ORIGIN,\n casdoorOrigin: normalized.casdoor.serverUrl,\n apiProxyPrefix: '/auth/',\n }),\n {\n status: 200,\n headers: {\n 'content-type': 'text/html; charset=utf-8',\n 'cache-control': 'no-store, max-age=0',\n },\n },\n );\n setPublicOriginCookie(response, origin, secure);\n return response;\n}\n\nexport async function createLoginEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n return createRedirectEntryResponse(request, config, 'login');\n}\n\nexport async function createSignupEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n return createRedirectEntryResponse(request, config, 'signup');\n}\n\nexport async function createAuthorizeEntryResponse(request: NextRequest, config: AuthKitConfig): Promise<NextResponse> {\n return createAuthorizePageResponse(request, config);\n}\n","const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\n\nfunction toBase64Url(bytes: ArrayBuffer): string {\n const raw = Buffer.from(bytes).toString('base64');\n return raw.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '');\n}\n\nexport async function createPkcePair(): Promise<{ verifier: string; challenge: string }> {\n const bytes = crypto.getRandomValues(new Uint8Array(48));\n const verifier = Array.from(bytes, (byte) => chars[byte % chars.length]).join('');\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n return { verifier, challenge: toBase64Url(digest) };\n}\n","import { NextResponse, type NextRequest } from 'next/server';\nimport type { AuthBusinessAdapter, AuthKitConfig, AuthPersistenceAdapter, AuthUser } from '../types';\nimport { normalizeAuthKitConfig } from '../core/config';\nimport { getRequestOrigin, getStoredPublicOrigin, clearPublicOriginCookie } from '../core/public-origin';\nimport { isSecureRequest } from '../core/request-security';\nimport { getAuthRedirectTarget, clearAuthRedirectCookie } from '../core/auth-redirect';\nimport {\n decodeCasdoorAccessToken,\n exchangeCasdoorOAuthToken,\n fetchCasdoorUserInfo,\n} from './oauth';\nimport { getCasdoorConfig } from './config';\nimport { getPkceCookieName, verifyState } from '../core/oauth-state';\nimport { encodeSessionToken } from '../core/session-token';\nimport { isGlobalAdminEmail } from '../core/admin';\nimport { resolvePostLoginRedirect } from '../core/redirect';\nimport { buildAuthUserFromProfile } from '../core/auth-role';\n\nexport interface CallbackHandlerOptions {\n config: AuthKitConfig;\n adapter?: AuthBusinessAdapter;\n persistence?: AuthPersistenceAdapter;\n}\n\nfunction readCookieHeaderValue(cookieHeader: string | null, name: string): string | null {\n if (!cookieHeader) {\n return null;\n }\n\n for (const entry of cookieHeader.split(';')) {\n const [rawName, ...valueParts] = entry.trim().split('=');\n if (rawName === name) {\n const value = valueParts.join('=').trim();\n return value || null;\n }\n }\n\n return null;\n}\n\nfunction getPublicOrigin(request: NextRequest, config: AuthKitConfig): string {\n return getStoredPublicOrigin(request) || getRequestOrigin(request, config.appUrl);\n}\n\nfunction rewriteToCallbackErrorPage(\n request: NextRequest,\n config: AuthKitConfig,\n title: string,\n message: string,\n details?: string,\n): NextResponse {\n const origin = getPublicOrigin(request, config);\n const targetUrl = new URL('/callback/error', origin);\n targetUrl.searchParams.set('title', title);\n targetUrl.searchParams.set('message', message);\n\n if (details) {\n targetUrl.searchParams.set('details', details);\n }\n\n return NextResponse.redirect(targetUrl, 307);\n}\n\nfunction getPkceCodeVerifier(request: NextRequest, state: string): string | null {\n return readCookieHeaderValue(request.headers.get('cookie'), getPkceCookieName(state));\n}\n\nfunction setNextAuthSessionCookies(response: NextResponse, sessionToken: string, isSecure: boolean): void {\n const cookieName = isSecure ? '__Secure-next-auth.session-token' : 'next-auth.session-token';\n const expires = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);\n const baseOptions = {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n secure: isSecure,\n expires,\n };\n const maxCookieSize = 3933;\n\n if (sessionToken.length <= maxCookieSize) {\n response.cookies.set(cookieName, sessionToken, baseOptions);\n return;\n }\n\n const chunkCount = Math.ceil(sessionToken.length / maxCookieSize);\n for (let index = 0; index < chunkCount; index++) {\n response.cookies.set(\n `${cookieName}.${index}`,\n sessionToken.slice(index * maxCookieSize, (index + 1) * maxCookieSize),\n baseOptions,\n );\n }\n}\n\nfunction sanitizeRedirectPath(value: string | null): string {\n if (!value || !value.startsWith('/') || value.startsWith('//')) {\n return '/user/account';\n }\n\n return value;\n}\n\nfunction summarizeCookieHeader(cookieHeader: string | null): Record<string, unknown> {\n if (!cookieHeader) {\n return { present: false };\n }\n\n const cookieNames = cookieHeader\n .split(';')\n .map((entry) => entry.trim().split('=')[0])\n .filter(Boolean);\n\n return {\n present: true,\n count: cookieNames.length,\n names: cookieNames,\n };\n}\n\nexport function mapProfileToAuthUser(profile: Awaited<ReturnType<typeof fetchCasdoorUserInfo>>, adapter?: AuthBusinessAdapter): AuthUser {\n const typedProfile = profile as Awaited<ReturnType<typeof fetchCasdoorUserInfo>> & {\n sub?: string;\n picture?: string;\n avatarUrl?: string;\n role?: string;\n };\n const email = typedProfile.email || null;\n const isAdmin =\n Boolean(typedProfile.isAdmin) ||\n Boolean(adapter?.isAdminEmail?.(email)) ||\n isGlobalAdminEmail(email);\n\n return buildAuthUserFromProfile(\n {\n id: typedProfile.id,\n sub: typedProfile.sub,\n name: typedProfile.name,\n displayName: typedProfile.displayName,\n email,\n picture: typedProfile.picture,\n avatarUrl: typedProfile.avatarUrl,\n isAdmin: typedProfile.isAdmin,\n role: typedProfile.role,\n },\n isAdmin,\n );\n}\n\nfunction getRedirectTarget(request: NextRequest, user: AuthUser, adapter?: AuthBusinessAdapter): string {\n const adapterRedirect = adapter?.resolvePostLoginRedirect?.(user);\n if (adapterRedirect) {\n return sanitizeRedirectPath(adapterRedirect);\n }\n\n const storedRedirect = getAuthRedirectTarget(request);\n if (storedRedirect) {\n return sanitizeRedirectPath(storedRedirect);\n }\n\n return sanitizeRedirectPath(resolvePostLoginRedirect(user, '/user/account'));\n}\n\nexport async function createCallbackResponse(\n request: NextRequest,\n options: CallbackHandlerOptions,\n): Promise<NextResponse> {\n const normalized = normalizeAuthKitConfig(options.config);\n const publicOrigin = getPublicOrigin(request, normalized);\n const url = new URL(request.url);\n const code = url.searchParams.get('code');\n const state = url.searchParams.get('state');\n const error = url.searchParams.get('error');\n const secure = normalized.cookie?.secure === 'auto'\n ? isSecureRequest(request, normalized.appUrl)\n : Boolean(normalized.cookie?.secure);\n\n if (error) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n 'Casdoor 返回了授权错误',\n '授权服务器在回调阶段返回了错误信息。请返回首页或重新登录后再试。',\n error,\n );\n }\n\n if (!code) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '缺少授权码',\n 'Casdoor 回调没有带回 code,这通常意味着授权流程未完成。',\n 'no_code',\n );\n }\n\n if (!state || !(await verifyState(state))) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '登录状态校验失败',\n '回调中的 state 与本次登录流程不匹配,请重新发起登录。',\n 'invalid_state',\n );\n }\n\n const codeVerifier = getPkceCodeVerifier(request, state);\n if (!codeVerifier) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '缺少 PKCE 校验值',\n '回调请求里没有找到 pkce_code_verifier cookie。请重新从登录入口发起流程。',\n 'missing_pkce_code_verifier',\n );\n }\n\n const casdoorConfig = getCasdoorConfig(normalized);\n const redirectUri = `${publicOrigin}${casdoorConfig.casdoor.redirectPath}`;\n const tokens = await exchangeCasdoorOAuthToken(casdoorConfig, code, redirectUri, codeVerifier);\n const accessToken = tokens.access_token ?? tokens.accessToken ?? '';\n\n if (!accessToken) {\n return rewriteToCallbackErrorPage(\n request,\n normalized,\n '缺少访问令牌',\n 'Casdoor 回调没有返回 access token。',\n 'missing_access_token',\n );\n }\n\n const profile = await fetchCasdoorUserInfo(casdoorConfig, accessToken);\n\n const decodedAccessToken = decodeCasdoorAccessToken(accessToken) as { exp?: number } | null;\n const mappedUser = options.adapter?.onUserSync\n ? await options.adapter.onUserSync(profile, {\n accessToken,\n refreshToken: tokens.refresh_token || tokens.refreshToken,\n idToken: tokens.id_token || tokens.idToken,\n expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1000 : tokens.expiresAt,\n })\n : mapProfileToAuthUser(profile, options.adapter);\n\n if (options.persistence?.syncAuthUser) {\n await options.persistence.syncAuthUser(mappedUser);\n }\n\n const sessionToken = await encodeSessionToken({\n token: {\n id: mappedUser.id,\n sub: mappedUser.id,\n userId: mappedUser.id,\n name: mappedUser.name,\n email: mappedUser.email,\n picture: mappedUser.image,\n accessToken,\n expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1000 : decodedAccessToken?.exp,\n isAdmin: mappedUser.isAdmin,\n role: mappedUser.role,\n tokenBalance: mappedUser.tokenBalance,\n isVip: mappedUser.isVip,\n },\n secret: normalized.nextauthSecret,\n maxAge: normalized.session?.maxAgeSeconds,\n });\n\n const response = NextResponse.redirect(new URL(getRedirectTarget(request, mappedUser, options.adapter), publicOrigin));\n setNextAuthSessionCookies(response, sessionToken, secure);\n response.cookies.set(getPkceCookieName(state), '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n response.cookies.set('oauth_state', '', {\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n secure,\n maxAge: 0,\n });\n clearAuthRedirectCookie(response, secure);\n clearPublicOriginCookie(response, secure);\n return response;\n}\n\nexport function createCallbackHandler(options: CallbackHandlerOptions) {\n return async function GET(request: NextRequest) {\n return createCallbackResponse(request, options);\n };\n}\n"],"mappings":"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","names":["Buffer","crypto","Buffer","crypto","Buffer","NextResponse","NextResponse","NextResponse"]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/core/redirect.ts
|
|
2
|
+
function buildAuthJumpHref(kind, redirect, basePath = "/auth") {
|
|
3
|
+
const normalizedBasePath = basePath ? basePath.startsWith("/") ? basePath : "/" + basePath : "";
|
|
4
|
+
const targetPath = (normalizedBasePath + "/" + kind).replace(/\/+/g, "/");
|
|
5
|
+
const url = new URL(targetPath, "http://localhost");
|
|
6
|
+
if (redirect) {
|
|
7
|
+
url.searchParams.set("redirect", redirect);
|
|
8
|
+
}
|
|
9
|
+
return url.pathname + url.search;
|
|
10
|
+
}
|
|
11
|
+
function resolvePostLoginRedirect(user, fallback = "/") {
|
|
12
|
+
if (user.role === "admin" || user.isAdmin) return "/admin";
|
|
13
|
+
return fallback;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/core/auth-role.ts
|
|
17
|
+
function resolveAuthUserRole(role, isAdmin) {
|
|
18
|
+
if (role === "admin" || role === "user") {
|
|
19
|
+
return role;
|
|
20
|
+
}
|
|
21
|
+
return isAdmin ? "admin" : "user";
|
|
22
|
+
}
|
|
23
|
+
function buildAuthUserFromProfile(profile, isAdmin) {
|
|
24
|
+
const role = resolveAuthUserRole(profile.role, isAdmin);
|
|
25
|
+
return {
|
|
26
|
+
id: profile.sub || profile.id || profile.email || "casdoor-user",
|
|
27
|
+
name: profile.name || profile.displayName || null,
|
|
28
|
+
email: profile.email || null,
|
|
29
|
+
image: profile.picture || profile.avatarUrl || null,
|
|
30
|
+
isAdmin: isAdmin || role === "admin",
|
|
31
|
+
role,
|
|
32
|
+
tokenBalance: Number(profile.tokenBalance ?? 2580),
|
|
33
|
+
isVip: Boolean(profile.isVip ?? true)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function buildAuthUserFromToken(token, isAdmin) {
|
|
37
|
+
const role = resolveAuthUserRole(token.role, isAdmin);
|
|
38
|
+
return {
|
|
39
|
+
id: token.userId || token.sub || token.id || token.email || "casdoor-user",
|
|
40
|
+
name: token.name ?? null,
|
|
41
|
+
email: token.email ?? null,
|
|
42
|
+
image: token.picture ?? null,
|
|
43
|
+
isAdmin: isAdmin || role === "admin",
|
|
44
|
+
role,
|
|
45
|
+
tokenBalance: Number(token.tokenBalance ?? 2580),
|
|
46
|
+
isVip: Boolean(token.isVip ?? true)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function buildAuthUserSummary(user) {
|
|
50
|
+
const isAuthenticated = Boolean(user);
|
|
51
|
+
const isAdmin = Boolean(user?.isAdmin) || user?.role === "admin";
|
|
52
|
+
const role = !isAuthenticated ? "guest" : resolveAuthUserRole(user?.role, isAdmin);
|
|
53
|
+
return {
|
|
54
|
+
id: user?.id ?? null,
|
|
55
|
+
name: user?.name || "\u767B\u5F55",
|
|
56
|
+
email: user?.email ?? null,
|
|
57
|
+
image: user?.image ?? user?.picture ?? null,
|
|
58
|
+
isAuthenticated,
|
|
59
|
+
isAdmin,
|
|
60
|
+
tokenBalance: Number(user?.tokenBalance ?? 2580),
|
|
61
|
+
isVip: Boolean(user?.isVip ?? true),
|
|
62
|
+
role
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
buildAuthJumpHref,
|
|
68
|
+
resolvePostLoginRedirect,
|
|
69
|
+
resolveAuthUserRole,
|
|
70
|
+
buildAuthUserFromProfile,
|
|
71
|
+
buildAuthUserFromToken,
|
|
72
|
+
buildAuthUserSummary
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=chunk-JCQ5P7QZ.js.map
|