package token import ( "encoding/base64" "encoding/json" "testing" "time" ) // buildTestJWT builds a JWT string with the given payload (no real signature). func buildTestJWT(claims map[string]interface{}) string { header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"RS256","typ":"JWT"}`)) payload, _ := json.Marshal(claims) payloadEnc := base64.RawURLEncoding.EncodeToString(payload) sig := base64.RawURLEncoding.EncodeToString([]byte("fakesig")) return header + "." + payloadEnc + "." + sig } func TestDecodePayload(t *testing.T) { claims := map[string]interface{}{ "iss": "https://id.example.com/realms/test", "sub": "user123", "exp": float64(1700000000), "aud": "nix-cache", } jwt := buildTestJWT(claims) decoded, err := DecodePayload(jwt) if err != nil { t.Fatalf("unexpected error: %v", err) } if decoded["iss"] != "https://id.example.com/realms/test" { t.Errorf("iss = %v, want %v", decoded["iss"], "https://id.example.com/realms/test") } if decoded["sub"] != "user123" { t.Errorf("sub = %v, want %v", decoded["sub"], "user123") } if decoded["aud"] != "nix-cache" { t.Errorf("aud = %v, want %v", decoded["aud"], "nix-cache") } } func TestExpiryInfo(t *testing.T) { futureExp := time.Now().Add(1 * time.Hour).Unix() claims := map[string]interface{}{ "exp": float64(futureExp), } exp, remaining := ExpiryInfo(claims) if exp.Unix() != futureExp { t.Errorf("exp = %v, want %v", exp.Unix(), futureExp) } if remaining < 59*time.Minute || remaining > 61*time.Minute { t.Errorf("remaining = %v, expected ~1 hour", remaining) } } func TestExpiryInfoPast(t *testing.T) { pastExp := time.Now().Add(-1 * time.Hour).Unix() claims := map[string]interface{}{ "exp": float64(pastExp), } _, remaining := ExpiryInfo(claims) if remaining >= 0 { t.Errorf("remaining = %v, expected negative (expired)", remaining) } } func TestDecodePayloadMalformed(t *testing.T) { tests := []struct { name string token string }{ {"no dots", "nodots"}, {"one dot", "one.dot"}, {"empty payload", "header..sig"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, err := DecodePayload(tt.token) if err == nil { t.Error("expected error, got nil") } }) } }