package bouncer import ( "testing" "time" "github.com/golang-jwt/jwt/v5" ) func TestMintClaims(t *testing.T) { issuer := "https://app.test/_user/api/v1/login" before := time.Now().Add(-2 * time.Second) token, jti, err := Mint(secret, "42", issuer, 60*time.Minute) after := time.Now().Add(2 * time.Second) if err != nil { t.Fatal(err) } if jti == "" { t.Fatal("empty jti") } claims := decodeClaims(t, token, secret) if claims["iss"] != issuer || claims["sub"] != "42" || claims["prv"] != "a867434cbc213adfbe78a02bed7082a6bd99c883" { t.Fatalf("claims = %#v", claims) } if claims["jti"] != jti { t.Fatalf("jti claim %v != returned %s", claims["jti"], jti) } iat := claimUnix(t, claims, "iat") nbf := claimUnix(t, claims, "nbf") exp := claimUnix(t, claims, "exp") if iat.Before(before) || iat.After(after) || nbf.Before(before) || nbf.After(after) { t.Fatalf("iat=%s nbf=%s want near now", iat, nbf) } if exp.Before(iat.Add(59*time.Minute)) || exp.After(iat.Add(61*time.Minute)) { t.Fatalf("exp=%s iat=%s", exp, iat) } sub, err := Verify(token, secret) if err != nil || sub != "42" { t.Fatalf("Verify = %q %v", sub, err) } } func decodeClaims(t *testing.T, token, key string) jwt.MapClaims { t.Helper() parser := jwt.NewParser(jwt.WithValidMethods([]string{"HS256"}), jwt.WithoutClaimsValidation()) claims := jwt.MapClaims{} if _, err := parser.ParseWithClaims(token, claims, func(*jwt.Token) (any, error) { return []byte(key), nil }); err != nil { t.Fatal(err) } return claims } func claimUnix(t *testing.T, claims jwt.MapClaims, key string) time.Time { t.Helper() v, ok := claims[key].(float64) if !ok { t.Fatalf("%s = %#v", key, claims[key]) } return time.Unix(int64(v), 0) }