# Google OAuth 登录集成文档

## 功能概述

实现了 Google OAuth 2.0 登录功能，参考 Discord 登录的实现模式，用户可以通过 Google 账号快速登录应用。

## 实现架构

### 1. OAuth 流程

```
用户点击 "Continue with Google"
    ↓
跳转到 Google 授权页面
    ↓
用户授权后，Google 重定向到回调 URL
    ↓
API 路由接收授权码并重定向回登录页
    ↓
前端获取授权码并调用后端登录接口
    ↓
登录成功，跳转到首页或指定页面
```

## 文件结构

```
src/
├── lib/
│   └── oauth/
│       ├── discord.ts          # Discord OAuth 配置
│       └── google.ts           # Google OAuth 配置 (新增)
├── app/
│   ├── (auth)/
│   │   └── login/
│   │       └── components/
│   │           ├── DiscordButton.tsx    # Discord 登录按钮
│   │           ├── GoogleButton.tsx     # Google 登录按钮 (新增)
│   │           └── login-form.tsx       # 登录表单 (已更新)
│   └── api/
│       └── auth/
│           ├── discord/
│           │   └── callback/
│           │       └── route.ts         # Discord 回调路由
│           └── google/
│               └── callback/
│                   └── route.ts         # Google 回调路由 (新增)
```

## 核心文件说明

### 1. Google OAuth 配置 (`src/lib/oauth/google.ts`)

```typescript
export const googleOAuth = {
  getAuthUrl: (state?: string): string => {
    // 构建 Google OAuth 授权 URL
    // 包含 client_id, redirect_uri, scope 等参数
  },
}
```

**配置参数**:

- `client_id`: Google OAuth 客户端 ID
- `redirect_uri`: 授权后的回调 URL
- `scope`: 请求的权限范围（email, profile）
- `access_type`: offline（获取 refresh_token）
- `prompt`: consent（每次都显示授权页面）

### 2. GoogleButton 组件 (`src/app/(auth)/login/components/GoogleButton.tsx`)

**功能**:

- 处理 Google 登录按钮点击事件
- 生成随机 state 用于安全验证
- 跳转到 Google 授权页面
- 处理 OAuth 回调（授权码）
- 调用后端登录接口
- 处理登录成功/失败的重定向

**关键方法**:

```typescript
const handleGoogleLogin = () => {
  // 1. 生成 state
  const state = Math.random().toString(36).substring(2, 15)

  // 2. 获取授权 URL
  const authUrl = googleOAuth.getAuthUrl(state)

  // 3. 保存 state 到 sessionStorage
  sessionStorage.setItem('google_oauth_state', state)

  // 4. 跳转到 Google 授权页面
  window.location.href = authUrl
}
```

**OAuth 回调处理**:

```typescript
useEffect(() => {
  const googleCode = searchParams.get('google_code')
  const googleState = searchParams.get('google_state')

  if (googleCode) {
    // 验证 state
    // 调用后端登录接口
    // 处理登录结果
  }
}, [])
```

### 3. Google 回调路由 (`src/app/api/auth/google/callback/route.ts`)

**功能**:

- 接收 Google OAuth 回调
- 提取授权码 (code) 和 state
- 重定向回登录页面，并将参数传递给前端

```typescript
export async function GET(request: NextRequest) {
  const code = searchParams.get('code')
  const state = searchParams.get('state')

  // 重定向到登录页，携带 google_code 和 google_state
  redirectUrl.searchParams.set('google_code', code)
  redirectUrl.searchParams.set('google_state', state)

  return NextResponse.redirect(redirectUrl)
}
```

## 环境变量配置

需要在 `.env.local` 中添加以下环境变量：

```bash
# Google OAuth 配置
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your_google_client_id_here
NEXT_PUBLIC_APP_URL=https://test.crushlevel.ai
```

### 获取 Google OAuth 凭据

1. 访问 [Google Cloud Console](https://console.cloud.google.com/)
2. 创建或选择一个项目
3. 启用 Google+ API
4. 创建 OAuth 2.0 客户端 ID
5. 配置授权重定向 URI：
   ```
   https://test.crushlevel.ai/api/auth/google/callback
   http://localhost:3000/api/auth/google/callback (开发环境)
   ```
6. 复制客户端 ID 到环境变量

## 后端接口要求

后端需要实现登录接口，接收以下参数：

```typescript
interface LoginRequest {
  appClient: AppClient.Web
  deviceCode: string // 设备唯一标识
  thirdToken: string // Google 授权码
  thirdType: ThirdType.Google // 第三方类型
}
```

后端需要：

1. 使用授权码向 Google 交换 access_token
2. 使用 access_token 获取用户信息
3. 创建或更新用户账号
4. 返回应用的登录 token

## 安全特性

### 1. State 参数验证

- 前端生成随机 state 并保存到 sessionStorage
- 回调时验证 state 是否匹配
- 防止 CSRF 攻击

### 2. 授权码模式

- 使用 OAuth 2.0 授权码流程
- 授权码只能使用一次
- Token 交换在后端进行，更安全

### 3. URL 参数清理

- 登录成功后清理 URL 中的敏感参数
- 防止参数泄露

## 用户体验优化

### 1. 重定向保持

```typescript
// 保存登录前的页面
sessionStorage.setItem('login_redirect_url', redirect || '')

// 登录成功后跳转回原页面
const loginRedirectUrl = sessionStorage.getItem('login_redirect_url')
if (loginRedirectUrl) {
  router.push(loginRedirectUrl)
}
```

### 2. 错误处理

- 授权失败时显示友好的错误提示
- 自动清理 URL 参数
- 不影响用户继续尝试登录

### 3. 加载状态

- 使用 `useLogin` Hook 的 loading 状态
- 可以添加 loading 动画提升体验

## 测试清单

### 本地测试

- [ ] 点击 Google 登录按钮跳转到 Google 授权页面
- [ ] 授权后正确回调到应用
- [ ] 授权码正确传递给后端
- [ ] 登录成功后跳转到首页
- [ ] State 参数验证正常工作
- [ ] 错误情况处理正确

### 生产环境测试

- [ ] 配置正确的回调 URL
- [ ] HTTPS 证书有效
- [ ] 环境变量配置正确
- [ ] 后端接口正常工作

## 常见问题

### 1. 回调 URL 不匹配

**错误**: `redirect_uri_mismatch`

**解决方案**:

- 检查 Google Cloud Console 中配置的回调 URL
- 确保 `NEXT_PUBLIC_APP_URL` 环境变量正确
- 开发环境和生产环境需要分别配置

### 2. State 验证失败

**错误**: "Google login failed"

**解决方案**:

- 检查 sessionStorage 是否正常工作
- 确保没有跨域问题
- 检查浏览器是否禁用了 cookie/storage

### 3. 授权码已使用

**错误**: 后端返回授权码无效

**解决方案**:

- 授权码只能使用一次
- 避免重复调用登录接口
- 清理 URL 参数防止页面刷新时重复使用

## 与 Discord 登录的对比

| 特性           | Discord                          | Google                               |
| -------------- | -------------------------------- | ------------------------------------ |
| OAuth Provider | Discord                          | Google                               |
| Scopes         | identify, email                  | userinfo.email, userinfo.profile     |
| 授权 URL       | discord.com/api/oauth2/authorize | accounts.google.com/o/oauth2/v2/auth |
| 回调路由       | /api/auth/discord/callback       | /api/auth/google/callback            |
| URL 参数       | discord_code, discord_state      | google_code, google_state            |
| ThirdType      | Discord                          | Google                               |

## 扩展建议

### 1. 添加 Apple 登录

参考 Google 登录的实现，创建：

- `src/lib/oauth/apple.ts`
- `src/app/(auth)/login/components/AppleButton.tsx`
- `src/app/api/auth/apple/callback/route.ts`

### 2. 统一 OAuth 处理

可以创建通用的 OAuth Hook：

```typescript
const useOAuthLogin = (provider: 'google' | 'discord' | 'apple') => {
  // 通用的 OAuth 登录逻辑
}
```

### 3. 添加登录统计

记录不同登录方式的使用情况，优化用户体验。

## 相关文档

- [Google OAuth 2.0 文档](https://developers.google.com/identity/protocols/oauth2)
- [Next.js API Routes](https://nextjs.org/docs/app/building-your-application/routing/route-handlers)
- Discord OAuth 实现参考
