From dd109a464acc7aacc21cf87d300824258723bb23 Mon Sep 17 00:00:00 2001 From: beilunyang <786220806@qq.com> Date: Sun, 7 Dec 2025 17:50:27 +0800 Subject: [PATCH] feat(auth): add Google OAuth support --- .env.example | 2 + README.md | 28 ++++++++--- app/components/auth/login-form.tsx | 30 +++++++++++ app/components/profile/profile-card.tsx | 67 ++++++++++++++++++++----- app/i18n/messages/en/auth.json | 3 +- app/i18n/messages/ja/auth.json | 3 +- app/i18n/messages/ko/auth.json | 3 +- app/i18n/messages/zh-CN/auth.json | 3 +- app/i18n/messages/zh-TW/auth.json | 3 +- app/lib/auth.ts | 25 ++++++--- next.config.ts | 4 ++ tsconfig.json | 24 +++++++-- types.d.ts | 3 +- 13 files changed, 162 insertions(+), 36 deletions(-) diff --git a/.env.example b/.env.example index 47684bd..4ae8726 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,7 @@ AUTH_GITHUB_ID = "" AUTH_GITHUB_SECRET = "" +AUTH_GOOGLE_ID = "" +AUTH_GOOGLE_SECRET = "" AUTH_SECRET = "" CLOUDFLARE_API_TOKEN = "" diff --git a/README.md b/README.md index 9765d0f..34fd98a 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ OpenAPI环境变量Github OAuth App 配置 • + Google OAuth App 配置贡献许可证交流群 • @@ -782,6 +783,8 @@ console.log('分享链接:', `https://your-domain.com/shared/message/${data.toke ### 认证相关 - `AUTH_GITHUB_ID`: GitHub OAuth App ID - `AUTH_GITHUB_SECRET`: GitHub OAuth App Secret +- `AUTH_GOOGLE_ID`: Google OAuth App ID +- `AUTH_GOOGLE_SECRET`: Google OAuth App Secret - `AUTH_SECRET`: NextAuth Secret,用来加密 session,请设置一个随机字符串 ### Cloudflare 配置 @@ -796,16 +799,29 @@ console.log('分享链接:', `https://your-domain.com/shared/message/${data.toke ## Github OAuth App 配置 -- 登录 [Github Developer](https://github.com/settings/developers) 创建一个新的 OAuth App -- 生成一个新的 `Client ID` 和 `Client Secret` -- 设置 `Application name` 为 `` -- 设置 `Homepage URL` 为 `https://` -- 设置 `Authorization callback URL` 为 `https:///api/auth/callback/github` +1. 登录 [Github Developer](https://github.com/settings/developers) 创建一个新的 OAuth App +2. 生成一个新的 `Client ID` 和 `Client Secret` +3. 配置参数: + - `Application name`: `` + - `Homepage URL`: `https://` + - `Authorization callback URL`: `https:///api/auth/callback/github` + +## Google OAuth App 配置 + +1. 访问 [Google Cloud Console](https://console.cloud.google.com/) 创建项目 +2. 配置 OAuth 同意屏幕 +3. 创建 OAuth 客户端 ID + - 应用类型:Web 应用 + - 已获授权的 Javascript 来源:`https://` + - 已获授权的重定向 URI:`https:///api/auth/callback/google` +4. 获取 `Client ID` 和 `Client Secret` +5. 配置环境变量 `AUTH_GOOGLE_ID` 和 `AUTH_GOOGLE_SECRET` + ## 贡献 -欢迎提交 Pull Request 或者 Issue来帮助改进这个项目 +欢迎提交 Pull Request 或者 Issue 来帮助改进这个项目 ## 许可证 diff --git a/app/components/auth/login-form.tsx b/app/components/auth/login-form.tsx index e2374b9..5fd5de2 100644 --- a/app/components/auth/login-form.tsx +++ b/app/components/auth/login-form.tsx @@ -200,6 +200,10 @@ export function LoginForm({ turnstile }: LoginFormProps) { signIn("github", { callbackUrl: "/" }) } + const handleGoogleLogin = () => { + signIn("google", { callbackUrl: "/" }) + } + return ( @@ -297,6 +301,32 @@ export function LoginForm({ turnstile }: LoginFormProps) { {t("actions.githubLogin")} + + diff --git a/app/components/profile/profile-card.tsx b/app/components/profile/profile-card.tsx index 1798d4c..e4705e6 100644 --- a/app/components/profile/profile-card.tsx +++ b/app/components/profile/profile-card.tsx @@ -26,6 +26,38 @@ const roleConfigs = { civilian: { key: 'CIVILIAN', icon: User2 }, } as const +const providerConfigs = { + google: { + label: "Google", + className: "text-red-500 bg-red-500/10", + icon: (props: any) => ( + + + + + + + ), + }, + github: { + label: "GitHub", + className: "text-primary bg-primary/10", + icon: Github, + }, +} as const + export function ProfileCard({ user }: ProfileCardProps) { const t = useTranslations("profile.card") const tAuth = useTranslations("auth.signButton") @@ -56,15 +88,24 @@ export function ProfileCard({ user }: ProfileCardProps) {

{user.name}

- { - user.email && ( - // 先简单实现,后续再完善 -
- - {tAuth("linked")} -
- ) - } + {!!user?.providers?.length && ( +
+ {user.providers.map((provider) => { + const config = providerConfigs[provider as keyof typeof providerConfigs] + if (!config) return null + const Icon = config.icon + return ( +
+ + {config.label} +
+ ) + })} +
+ )}

{ @@ -78,7 +119,7 @@ export function ProfileCard({ user }: ProfileCardProps) { const Icon = roleConfig.icon const roleName = t(`roles.${roleConfig.key}` as any) return ( -

}
- -