64 lines
2.4 KiB
Go
64 lines
2.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"crypto"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/example/ollama-fair-gateway/internal/config"
|
|
)
|
|
|
|
func TestOIDCVerifierRS256(t *testing.T) {
|
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var issuer string
|
|
mux := http.NewServeMux()
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
issuer = srv.URL
|
|
mux.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) {
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"issuer": issuer, "jwks_uri": issuer + "/jwks"})
|
|
})
|
|
mux.HandleFunc("/jwks", func(w http.ResponseWriter, r *http.Request) {
|
|
e := big.NewInt(int64(key.PublicKey.E)).Bytes()
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"keys": []any{map[string]any{"kty": "RSA", "kid": "k1", "alg": "RS256", "n": base64.RawURLEncoding.EncodeToString(key.PublicKey.N.Bytes()), "e": base64.RawURLEncoding.EncodeToString(e)}}})
|
|
})
|
|
v, err := NewOIDCVerifier(context.Background(), config.OIDCConfig{Enabled: true, Issuer: issuer, Audience: "gateway", TenantClaim: "tenant", ApplicationClaim: "azp", GroupsClaim: "groups", AdminGroups: []string{"admins"}, ClockSkew: config.Duration(time.Second), JWKSRefreshMinInterval: config.Duration(time.Second), AllowedAlgorithms: []string{"RS256"}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
now := time.Now()
|
|
tok := signRS256(t, key, "k1", map[string]any{"iss": issuer, "aud": "gateway", "sub": "alice", "tenant": "team-a", "azp": "web", "groups": []string{"admins"}, "exp": now.Add(time.Minute).Unix(), "nbf": now.Add(-time.Second).Unix()})
|
|
id, err := v.Verify(context.Background(), tok)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if id.Tenant != "team-a" || id.Subject != "alice" || id.Application != "web" || !id.IsAdmin() {
|
|
t.Fatalf("unexpected identity: %#v", id)
|
|
}
|
|
}
|
|
func signRS256(t *testing.T, key *rsa.PrivateKey, kid string, claims map[string]any) string {
|
|
t.Helper()
|
|
h, _ := json.Marshal(map[string]any{"alg": "RS256", "typ": "JWT", "kid": kid})
|
|
p, _ := json.Marshal(claims)
|
|
a := base64.RawURLEncoding.EncodeToString(h) + "." + base64.RawURLEncoding.EncodeToString(p)
|
|
sum := sha256.Sum256([]byte(a))
|
|
sig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, sum[:])
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return fmt.Sprintf("%s.%s", a, base64.RawURLEncoding.EncodeToString(sig))
|
|
}
|