package auth_test import ( "testing" "switchboard-core/auth" ) func TestOIDCProvider_Discovery(t *testing.T) { idp := newMockIdP() defer idp.Close() p, err := auth.NewOIDCProvider(auth.OIDCConfig{ IssuerURL: idp.IssuerURL(), ClientID: "switchboard", ClientSecret: "secret", AutoActivate: true, }) if err != nil { t.Fatalf("NewOIDCProvider: %v", err) } disc := p.Discovery() if disc == nil { t.Fatal("discovery should not be nil") } if disc.JWKSUri == "" { t.Error("JWKS URI should not be empty") } if disc.TokenEndpoint == "" { t.Error("token endpoint should not be empty") } } func TestOIDCProvider_Mode(t *testing.T) { idp := newMockIdP() defer idp.Close() p, err := auth.NewOIDCProvider(auth.OIDCConfig{ IssuerURL: idp.IssuerURL(), ClientID: "switchboard", }) if err != nil { t.Fatalf("NewOIDCProvider: %v", err) } if p.Mode() != auth.ModeOIDC { t.Errorf("Mode() = %q, want %q", p.Mode(), auth.ModeOIDC) } } func TestOIDCProvider_NoRegistration(t *testing.T) { idp := newMockIdP() defer idp.Close() p, err := auth.NewOIDCProvider(auth.OIDCConfig{ IssuerURL: idp.IssuerURL(), ClientID: "switchboard", }) if err != nil { t.Fatalf("NewOIDCProvider: %v", err) } if p.SupportsRegistration() { t.Error("OIDC should not support registration") } } func TestOIDCProvider_MissingIssuer(t *testing.T) { _, err := auth.NewOIDCProvider(auth.OIDCConfig{ ClientID: "switchboard", }) if err == nil { t.Error("expected error for missing issuer URL") } } func TestOIDCProvider_MissingClientID(t *testing.T) { idp := newMockIdP() defer idp.Close() _, err := auth.NewOIDCProvider(auth.OIDCConfig{ IssuerURL: idp.IssuerURL(), }) if err == nil { t.Error("expected error for missing client ID") } } func TestOIDCProvider_AuthorizationURL(t *testing.T) { idp := newMockIdP() defer idp.Close() p, err := auth.NewOIDCProvider(auth.OIDCConfig{ IssuerURL: idp.IssuerURL(), ClientID: "switchboard", }) if err != nil { t.Fatalf("NewOIDCProvider: %v", err) } url := p.AuthorizationURL("test-state", "test-nonce", "http://localhost/callback") if url == "" { t.Fatal("AuthorizationURL should not be empty") } // Should contain the required OIDC parameters for _, want := range []string{"response_type=code", "client_id=switchboard", "state=test-state", "nonce=test-nonce"} { if !containsStr(url, want) { t.Errorf("AuthorizationURL missing %q in %q", want, url) } } } func TestOIDCProvider_UnreachableIssuer(t *testing.T) { _, err := auth.NewOIDCProvider(auth.OIDCConfig{ IssuerURL: "http://127.0.0.1:1/unreachable", ClientID: "switchboard", }) if err == nil { t.Error("expected error for unreachable issuer") } } func containsStr(s, substr string) bool { return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsSubstring(s, substr)) } func containsSubstring(s, sub string) bool { for i := 0; i <= len(s)-len(sub); i++ { if s[i:i+len(sub)] == sub { return true } } return false }