fix(auth): preserve resolved token version on oauth login

This commit is contained in:
IanShaw027
2026-04-22 16:01:25 +08:00
parent ca4e38aa01
commit 82259d1380
4 changed files with 29 additions and 7 deletions

View File

@@ -778,6 +778,14 @@ func TestExchangePendingOAuthCompletionExistingLoginWithSuggestedProfileSkipsAdo
require.Equal(t, "https://cdn.example/existing-login.png", payload["suggested_avatar_url"])
require.NotContains(t, payload, "adoption_required")
accessToken, ok := payload["access_token"].(string)
require.True(t, ok)
claims, err := handler.authService.ValidateToken(accessToken)
require.NoError(t, err)
reloadedUser, err := handler.userService.GetByID(ctx, userEntity.ID)
require.NoError(t, err)
require.Equal(t, reloadedUser.TokenVersion, claims.TokenVersion)
decisionCount, err := client.IdentityAdoptionDecision.Query().
Where(identityadoptiondecision.PendingAuthSessionIDEQ(session.ID)).
Count(ctx)
@@ -2033,6 +2041,13 @@ func TestLogin2FACompletesPendingOAuthBindAndConsumesSession(t *testing.T) {
payload := decodeJSONResponseData(t, recorder)
require.NotEmpty(t, payload["access_token"])
require.NotEmpty(t, payload["refresh_token"])
accessToken, ok := payload["access_token"].(string)
require.True(t, ok)
claims, err := handler.authService.ValidateToken(accessToken)
require.NoError(t, err)
reloadedUser, err := handler.userService.GetByID(ctx, existingUser.ID)
require.NoError(t, err)
require.Equal(t, reloadedUser.TokenVersion, claims.TokenVersion)
identity, err := client.AuthIdentity.Query().
Where(

View File

@@ -1500,6 +1500,9 @@ func resolvedTokenVersion(user *User) int64 {
if user == nil {
return 0
}
if user.TokenVersionResolved {
return user.TokenVersion
}
material := strings.ToLower(strings.TrimSpace(user.Email)) + "\n" + user.PasswordHash
sum := sha256.Sum256([]byte(material))

View File

@@ -23,12 +23,15 @@ type User struct {
Status string
AllowedGroups []int64
TokenVersion int64 // Incremented on password change to invalidate existing tokens
SignupSource string
LastLoginAt *time.Time
LastActiveAt *time.Time
LastUsedAt *time.Time
CreatedAt time.Time
UpdatedAt time.Time
// TokenVersionResolved indicates TokenVersion already contains the fingerprint-derived
// value expected in JWT claims and refresh-token state.
TokenVersionResolved bool
SignupSource string
LastLoginAt *time.Time
LastActiveAt *time.Time
LastUsedAt *time.Time
CreatedAt time.Time
UpdatedAt time.Time
// GroupRates 用户专属分组倍率配置
// map[groupID]rateMultiplier

View File

@@ -943,10 +943,11 @@ func (s *UserService) GetByID(ctx context.Context, id int64) (*User, error) {
}
func normalizeLoadedUserTokenVersion(user *User) {
if user == nil {
if user == nil || user.TokenVersionResolved {
return
}
user.TokenVersion = resolvedTokenVersion(user)
user.TokenVersionResolved = true
}
// TouchLastActive 通过防抖更新 users.last_active_at减少鉴权热路径写放大。