package jwt import ( "testing" jwtv5 "github.com/golang-jwt/jwt/v5" ) // TestTokenPairRoundTrip 覆盖签发 + 解析,并校验 access token 类型。 func TestTokenPairRoundTrip(t *testing.T) { pair, err := GenerateTokenPair(42, "alice", "admin", 3) if err != nil { t.Fatalf("GenerateTokenPair: %v", err) } if pair.AccessToken == "" || pair.RefreshToken == "" { t.Fatal("tokens must not be empty") } claims, err := ParseToken(pair.AccessToken) if err != nil { t.Fatalf("ParseToken(access): %v", err) } if claims.UserID != 42 || claims.Username != "alice" || claims.Role != "admin" { t.Fatalf("unexpected claims: %+v", claims) } if claims.TokenType != "access" { t.Fatalf("access token should have tokenType=access, got %q", claims.TokenType) } if claims.TokenVersion != 3 { t.Fatalf("access token should carry tokenVersion=3, got %d", claims.TokenVersion) } } // TestRefreshRequiresRefreshToken 覆盖 token 类型强制: // 用 access token 刷新必须被拒;refresh token 应解析成功并携带版本。 func TestRefreshRequiresRefreshToken(t *testing.T) { pair, _ := GenerateTokenPair(1, "bob", "user", 0) if _, err := ParseRefreshToken(pair.AccessToken); err == nil { t.Fatal("ParseRefreshToken must reject access tokens") } claims, err := ParseRefreshToken(pair.RefreshToken) if err != nil { t.Fatalf("ParseRefreshToken(refresh): %v", err) } if claims.UserID != 1 || claims.TokenType != "refresh" { t.Fatalf("unexpected refresh claims: %+v", claims) } } // TestParseTokenRejectsBogus 解析任意非 JWT 字符串必须失败。 func TestParseTokenRejectsBogus(t *testing.T) { if _, err := ParseToken("not-a-jwt"); err == nil { t.Fatal("ParseToken must reject bogus token") } } // TestParseTokenRejectsNoneAlgo 覆盖算法混淆攻击防护: // ParseToken 的 keyfunc 仅接受 HMAC,alg=none 构造的 token 必须被拒。 func TestParseTokenRejectsNoneAlgo(t *testing.T) { tok := jwtv5.NewWithClaims(jwtv5.SigningMethodNone, Claims{UserID: 1, TokenType: "access"}) unsigned, err := tok.SigningString() if err != nil { t.Fatal(err) } bogus := unsigned + "." // alg=none 的无签名形式 if _, err := ParseToken(bogus); err == nil { t.Fatal("ParseToken must reject alg=none (algorithm confusion)") } }