feat(auth): 实现 Refresh Token 机制

- 新增 Access Token + Refresh Token 双令牌认证
- 支持 Token 自动刷新和轮转
- 添加登出和撤销所有会话接口
- 前端实现无感刷新和主动刷新定时器
This commit is contained in:
shaw
2026-02-05 12:38:48 +08:00
parent 05af95dade
commit 49a3c43741
17 changed files with 1119 additions and 73 deletions

View File

@@ -211,7 +211,7 @@ func (h *AuthHandler) LinuxDoOAuthCallback(c *gin.Context) {
email = linuxDoSyntheticEmail(subject)
}
jwtToken, _, err := h.authService.LoginOrRegisterOAuth(c.Request.Context(), email, username)
tokenPair, _, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username)
if err != nil {
// 避免把内部细节泄露给客户端;给前端保留结构化原因与提示信息即可。
redirectOAuthError(c, frontendCallback, "login_failed", infraerrors.Reason(err), infraerrors.Message(err))
@@ -219,7 +219,9 @@ func (h *AuthHandler) LinuxDoOAuthCallback(c *gin.Context) {
}
fragment := url.Values{}
fragment.Set("access_token", jwtToken)
fragment.Set("access_token", tokenPair.AccessToken)
fragment.Set("refresh_token", tokenPair.RefreshToken)
fragment.Set("expires_in", fmt.Sprintf("%d", tokenPair.ExpiresIn))
fragment.Set("token_type", "Bearer")
fragment.Set("redirect", redirectTo)
redirectWithFragment(c, frontendCallback, fragment)