Skip to content

Commit 8b42598

Browse files
authored
Merge pull request #5 from database-playground/pan93412/dbp-20-設計一個比較正常的-oauth
DBP-20: redesign authentication
2 parents f9d1b0e + dd40856 commit 8b42598

File tree

13 files changed

+1069
-652
lines changed

13 files changed

+1069
-652
lines changed

cmd/backend/dependencies.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,10 @@ func GinEngine(services []httpapi.Service, authStorage auth.Storage, gqlgenHandl
7777
engine.Use(gin.Recovery())
7878
engine.Use(httputils.MachineMiddleware())
7979
engine.Use(cors.New(cors.Config{
80-
AllowOrigins: cfg.AllowedOrigins,
81-
AllowMethods: []string{"GET", "POST", "OPTIONS"},
82-
AllowHeaders: []string{"Content-Type", "User-Agent", "Referer"},
83-
AllowCredentials: true,
84-
MaxAge: 24 * time.Hour,
80+
AllowOrigins: cfg.AllowedOrigins,
81+
AllowMethods: []string{"GET", "POST", "OPTIONS"},
82+
AllowHeaders: []string{"Content-Type", "User-Agent", "Referer", "Authorization"},
83+
MaxAge: 24 * time.Hour,
8584
}))
8685

8786
router := engine.Group("/")

docs/config.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ Database Playground 使用 PostgreSQL 作為資料庫。
4444

4545
這個 backend 以 Google OAuth 登入為主。
4646

47+
- `GAUTH_SECRET`:用來加密認證相關請求的 secret
4748
- `GAUTH_CLIENT_ID`:Google OAuth 的 Client ID
4849
- `GAUTH_CLIENT_SECRET`:Google OAuth 的 Client Secret
4950
- `GAUTH_REDIRECT_URIS`:在完成 Google OAuth 流程後,允許重新導向到的 URIs。
5051
- 舉例:`https://admin.dbplay.app`
5152

52-
Google OAuth 的登入起始連結為 `https://backend.yourdomain.tld/api/auth/google/login`,可選擇性帶入 `state` 參數。
53-
Google OAuth 的回呼連結為 `https://backend.yourdomain.tld/api/auth/google/callback`
53+
OAuth 的使用方式請參考 [Auth 端點](../httpapi/auth/README.md) 內容。
54+
55+
Google OAuth 的「已授權的重新導向 URI」應包含 `https://HOST/api/auth/v2/callback/google` 端點。
5456

5557
## SQL Runner
5658

httpapi/auth/README.md

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,100 @@
22

33
Auth 端點提供適合供網頁應用程式使用的認證 API。
44

5+
## 登入帳號
6+
7+
使用 `GET /api/auth/v2/authorize/google` 登入帳號。
8+
9+
GET 時,您需要帶入這些查詢參數 (query string):
10+
11+
- `response_type`:目前只支援授權碼模式,必須是 `code`
12+
- `redirect_uri`:要接收 token 的 callback endpoint,比如 `https://www.dbplay.app/api/auth/callback`
13+
- `state`:要傳給 redirect URI 的狀態參數
14+
- `code_challenge`:雜湊後的授權碼,在 callback 中取回 token 時會用到。
15+
- `code_challenge_method`:必須是 `S256`
16+
17+
`code_challenge` 的雜湊方式如下:
18+
19+
```plain
20+
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
21+
```
22+
23+
登入完成後,會自動跳轉到 `redirect_uri` 上,接著您可以在 redirect URI(下稱 callback)中取回 token。
24+
25+
### Callback 會收到的參數
26+
27+
在驗證完成後,瀏覽器會跳轉到 `redirect_uri`,並帶入以下的查詢字串:
28+
29+
- `code`:取回 token 的授權碼
30+
- `state`:你在〈登入帳號〉中傳入的狀態參數
31+
- `code_challenge`:你在〈登入帳號〉中傳入的雜湊授權碼
32+
- `code_challenge_method`:你在〈登入帳號〉中傳入的雜湊授權碼
33+
34+
接著您可以使用〈取回 token〉API 來取得 token。
35+
36+
如果登入失敗,則是會帶入以下的查詢字串:
37+
38+
- `error`:錯誤代碼
39+
- `error_description`:錯誤描述
40+
41+
## 取回 token
42+
43+
使用 `POST /api/auth/v2/token` 取回 token。
44+
45+
POST 時,您需要帶入這些查詢參數 (query string):
46+
47+
- `grant_type`:目前只支援授權碼模式,必須是 `authorization_code`
48+
- `code`:你在 `redirect_uri` 收到的授權碼
49+
- `redirect_uri`:重新導向連結,必須與〈登入帳號〉的 redirect URI 相同
50+
51+
如果一切順利的話,會回傳 token、token type、過期時間等資訊:
52+
53+
```json
54+
{
55+
"token_type": "Bearer",
56+
"access_token": "2YotnFZFEjr1zCsicMWpAA",
57+
"expires_in": 28800
58+
}
59+
```
60+
61+
## 授權
62+
63+
請將 access token 帶入 `Authorization` 標頭中,格式如下:
64+
65+
```plain
66+
Authorization: Bearer <access_token>
67+
```
68+
69+
預設 `access_token` 會存活 8 小時,且只要 token 有人存取就會延長。
70+
71+
如果需要登出的話,除了使用〈登出帳號〉API 撤銷特定 token 外,也可以使用 GraphQL 的批次撤銷來處理。
72+
573
## 登出帳號
674

7-
您可以使用 `POST /api/logout` 登出帳號。
75+
您可以使用 `POST /api/auth/v2/revoke` 登出帳號。
76+
77+
需要帶入以 `application/x-www-form-urlencoded` 編碼的請求體:
78+
79+
- `token`:要 revoke 的 token
80+
- `token_type_hint`:必須是 `access_token`
881

982
如果 Token 撤回失敗,則會回傳 HTTP 500 錯誤並帶上錯誤資訊:
1083

1184
```json
1285
{
13-
"error": "Failed to revoke the token. Please try again later.",
14-
"detail": "(error details)",
86+
"error": "server_error",
87+
"error_description": "Failed to revoke the token. Please try again later."
1588
}
1689
```
1790

18-
如果 Token 撤回成功,則回傳 HTTP 205 (Reset Content),此時您可以重新整理登入狀態。
91+
如果 Token 撤回成功,則回傳 HTTP 200 OK,此時您可以重新整理登入狀態。
1992

20-
如果沒有 Auth Token 或者是 token 無效,則依然回傳 HTTP 205。請引導使用者重新登入。
93+
如果沒有 Auth Token 或者是 token 無效,則依然回傳 HTTP 200。請引導使用者重新登入。
2194

22-
## Google 登入
95+
## 參考來源
2396

24-
如果您要觸發 Google 登入的流程,請前往 `GET /api/auth/google/login`。可以帶入 `redirect_uri` 參數來在登入完成後轉導到指定畫面。
97+
為了保證登入時的資訊安全,這裡參考了兩份 RFC 進行 API 的設計:
2598

26-
這個頁面會重新導向到 Google 的登入頁面,登入後會回到 `POST /api/auth/google/callback` 並進行帳號登入和註冊手續。
99+
- [RFC 6749 – The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749#autoid-35)
100+
- [RFC 7636 – Proof Key for Code Exchange by OAuth Public Clients](https://datatracker.ietf.org/doc/html/rfc7636#section-4.1)
101+
- [RFC 7009 – OAuth 2.0 Token Revocation](https://datatracker.ietf.org/doc/html/rfc7009)

0 commit comments

Comments
 (0)