forked from 77media/video-flow
121 lines
2.7 KiB
Markdown
121 lines
2.7 KiB
Markdown
# Google OAuth 前端接入说明
|
||
|
||
该文档面向前端同学,描述最新的 Google 登录/注册接入方式。
|
||
|
||
---
|
||
|
||
## 一、整体流程
|
||
|
||
```
|
||
用户 → Google 授权 → 回到前端回调页
|
||
前端回调页读取 code/state → 调用 Python /api/oauth/google
|
||
Python 返回 token/user 给前端 → 前端完成登录态落地
|
||
```
|
||
|
||
---
|
||
|
||
## 二、Google 控制台配置
|
||
|
||
在 Google Cloud Console → API 与服务 → 凭据 → 选择"Web 应用的客户端 ID":
|
||
|
||
### Authorized JavaScript origins(已授权的 JavaScript 来源)
|
||
- `https://www.movieflow.net`
|
||
- `https://www.movieflow.ai`
|
||
|
||
### Authorized redirect URIs(已授权的重定向 URI)
|
||
- `https://www.movieflow.net/api/auth/google/callback`
|
||
- `https://www.movieflow.ai/api/auth/google/callback`
|
||
|
||
本地调试(可选):
|
||
- JavaScript origins: `http://localhost:3000`
|
||
- Redirect URIs: `http://localhost:3000/api/auth/google/callback`
|
||
|
||
---
|
||
|
||
## 三、前端调用
|
||
|
||
### 第一步:Google 授权回调
|
||
在前端回调页(`/api/auth/google/callback`)读取 Google 返回的 `code` 与 `state`。
|
||
|
||
### 第二步:调用 Python 接口
|
||
- **路径**:`POST ${NEXT_PUBLIC_SMARTVIDEO_URL}/api/oauth/google`
|
||
- **请求体**:
|
||
```json
|
||
{
|
||
"code": "string",
|
||
"state": "string",
|
||
"invite_code": "string | null"
|
||
}
|
||
```
|
||
|
||
- **响应**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"token": "string",
|
||
"user": {
|
||
"userId": "string",
|
||
"userName": "string",
|
||
"name": "string",
|
||
"email": "string",
|
||
"authType": "GOOGLE",
|
||
"avatar": "string",
|
||
"isNewUser": true
|
||
},
|
||
"message": "Google OAuth successful"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 前端代码示例
|
||
```typescript
|
||
const baseUrl = process.env.NEXT_PUBLIC_SMARTVIDEO_URL;
|
||
const res = await fetch(`${baseUrl}/api/oauth/google`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Accept': 'application/json'
|
||
},
|
||
body: JSON.stringify({ code, state, invite_code })
|
||
});
|
||
|
||
const result = await res.json();
|
||
if (result.success) {
|
||
const { token, user } = result.data;
|
||
// 持久化 token & user
|
||
} else {
|
||
// 统一错误提示 result.message
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、环境变量
|
||
|
||
- `NEXT_PUBLIC_SMARTVIDEO_URL`:后端 Python 服务地址
|
||
|
||
---
|
||
|
||
## 五、错误处理
|
||
|
||
常见错误码:
|
||
- `GOOGLE_TOKEN_EXCHANGE_FAILED`:授权码交换失败
|
||
- `INVALID_ID_TOKEN`:ID Token 无效
|
||
- `UPSTREAM_AUTH_ERROR`:用户服务异常
|
||
|
||
前端统一处理:基于 `success=false` 与 `message` 提示用户。
|
||
|
||
---
|
||
|
||
## 六、安全建议
|
||
|
||
- 启用 PKCE
|
||
- 在 `state` 中绑定 CSRF 防护信息
|
||
- 确保回调地址与发起授权时的 `redirect_uri` 完全一致
|
||
|
||
---
|
||
|
||
文档版本:v4.0
|
||
更新时间:2025-09-23
|
||
适用范围:video-flow-b 前端项目 |