fix: enhance OAuth configuration and add debugging - Add Google OAuth authorization parameters - Add environment variable validation - Add debugging logs for redirect callback - Create OAuth configuration check script
This commit is contained in:
143
lib/auth.ts
143
lib/auth.ts
@ -7,42 +7,31 @@ import CredentialsProvider from "next-auth/providers/credentials";
|
||||
import { UserService } from "./services/user.service";
|
||||
import { AuthOptions } from "next-auth";
|
||||
|
||||
// 验证和清理 NEXTAUTH_URL
|
||||
function getValidatedNextAuthUrl(): string {
|
||||
const url = process.env.NEXTAUTH_URL;
|
||||
if (!url) {
|
||||
throw new Error("NEXTAUTH_URL 环境变量未设置");
|
||||
}
|
||||
// 验证环境变量
|
||||
function validateAuthConfig() {
|
||||
const requiredEnvVars = [
|
||||
'GOOGLE_CLIENT_ID',
|
||||
'GOOGLE_CLIENT_SECRET',
|
||||
'NEXTAUTH_SECRET',
|
||||
'NEXTAUTH_URL'
|
||||
];
|
||||
|
||||
const missingVars = requiredEnvVars.filter(varName => !process.env[varName]);
|
||||
|
||||
// 清理 URL,移除多余的引号
|
||||
let cleanUrl = url.trim();
|
||||
if (cleanUrl.startsWith('"') && cleanUrl.endsWith('"')) {
|
||||
cleanUrl = cleanUrl.slice(1, -1);
|
||||
if (missingVars.length > 0) {
|
||||
console.error('Missing required environment variables:', missingVars);
|
||||
throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
|
||||
}
|
||||
if (cleanUrl.startsWith("'") && cleanUrl.endsWith("'")) {
|
||||
cleanUrl = cleanUrl.slice(1, -1);
|
||||
}
|
||||
|
||||
// 确保 URL 格式正确
|
||||
try {
|
||||
new URL(cleanUrl);
|
||||
} catch (error) {
|
||||
throw new Error(`无效的 NEXTAUTH_URL: ${cleanUrl}`);
|
||||
}
|
||||
|
||||
return cleanUrl;
|
||||
|
||||
console.log('Auth configuration validated:', {
|
||||
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
|
||||
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID?.substring(0, 20) + '...',
|
||||
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET ? 'Set' : 'Missing'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取域名用于 Cookie 配置
|
||||
function getDomain(): string {
|
||||
const url = getValidatedNextAuthUrl();
|
||||
try {
|
||||
const urlObj = new URL(url);
|
||||
return urlObj.hostname;
|
||||
} catch {
|
||||
return "recorder.zyj.best"; // 默认域名
|
||||
}
|
||||
}
|
||||
// 验证配置
|
||||
validateAuthConfig();
|
||||
|
||||
export const authOptions: AuthOptions = {
|
||||
adapter: PrismaAdapter(prisma),
|
||||
@ -51,6 +40,13 @@ export const authOptions: AuthOptions = {
|
||||
GoogleProvider({
|
||||
clientId: process.env.GOOGLE_CLIENT_ID!,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
||||
authorization: {
|
||||
params: {
|
||||
prompt: "consent",
|
||||
access_type: "offline",
|
||||
response_type: "code"
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
CredentialsProvider({
|
||||
@ -117,10 +113,22 @@ export const authOptions: AuthOptions = {
|
||||
},
|
||||
|
||||
async redirect({ url, baseUrl }) {
|
||||
// 调试信息
|
||||
console.log("Redirect callback:", { url, baseUrl });
|
||||
|
||||
// 确保重定向到正确的页面
|
||||
if (url.startsWith("/")) return `${baseUrl}${url}`;
|
||||
else if (new URL(url).origin === baseUrl) return url;
|
||||
return `${baseUrl}/dashboard`;
|
||||
if (url.startsWith("/")) {
|
||||
const redirectUrl = `${baseUrl}${url}`;
|
||||
console.log("Redirecting to:", redirectUrl);
|
||||
return redirectUrl;
|
||||
} else if (new URL(url).origin === baseUrl) {
|
||||
console.log("Redirecting to same origin:", url);
|
||||
return url;
|
||||
}
|
||||
|
||||
const defaultUrl = `${baseUrl}/dashboard`;
|
||||
console.log("Redirecting to default:", defaultUrl);
|
||||
return defaultUrl;
|
||||
},
|
||||
},
|
||||
|
||||
@ -131,69 +139,4 @@ export const authOptions: AuthOptions = {
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
|
||||
debug: process.env.NODE_ENV === "development",
|
||||
|
||||
// 添加 Cookie 配置
|
||||
cookies: {
|
||||
sessionToken: {
|
||||
name: `next-auth.session-token`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
domain: process.env.NODE_ENV === "production" ? getDomain() : undefined,
|
||||
},
|
||||
},
|
||||
callbackUrl: {
|
||||
name: `next-auth.callback-url`,
|
||||
options: {
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
domain: process.env.NODE_ENV === "production" ? getDomain() : undefined,
|
||||
},
|
||||
},
|
||||
csrfToken: {
|
||||
name: `next-auth.csrf-token`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
domain: process.env.NODE_ENV === "production" ? getDomain() : undefined,
|
||||
},
|
||||
},
|
||||
pkceCodeVerifier: {
|
||||
name: `next-auth.pkce.code_verifier`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
maxAge: 900,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
domain: process.env.NODE_ENV === "production" ? getDomain() : undefined,
|
||||
},
|
||||
},
|
||||
state: {
|
||||
name: `next-auth.state`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
maxAge: 900,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
domain: process.env.NODE_ENV === "production" ? getDomain() : undefined,
|
||||
},
|
||||
},
|
||||
nonce: {
|
||||
name: `next-auth.nonce`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
domain: process.env.NODE_ENV === "production" ? getDomain() : undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user