package domain import ( "reflect" "testing" ) func TestHydraClient_HeadlessLoginFlags(t *testing.T) { t.Run("metadata-backed headless login client is supported", func(t *testing.T) { client := HydraClient{ TokenEndpointAuthMethod: "none", Metadata: map[string]any{ "headless_login_enabled": true, "headless_token_endpoint_auth_method": "private_key_jwt", "headless_jwks_uri": "https://rp.example.com/.well-known/jwks.json", }, } if !client.SupportsHeadlessLogin() { t.Fatalf("expected metadata-backed headless login client") } if !client.IsHeadlessLoginEnabled() { t.Fatalf("expected metadata-backed headless login enabled") } }) t.Run("inline jwks without jwks uri does not support headless login", func(t *testing.T) { client := HydraClient{ TokenEndpointAuthMethod: "private_key_jwt", JWKS: map[string]any{ "keys": []map[string]any{{ "kty": "RSA", }}, }, Metadata: map[string]any{ "headless_login_enabled": true, }, } if client.SupportsHeadlessLogin() { t.Fatalf("expected headless login prerequisites to be missing") } if client.IsHeadlessLoginEnabled() { t.Fatalf("expected headless login disabled without jwks uri") } }) t.Run("jwks uri without private_key_jwt does not support headless login", func(t *testing.T) { client := HydraClient{ TokenEndpointAuthMethod: "none", JWKSUri: "https://rp.example.com/.well-known/jwks.json", Metadata: map[string]any{ "headless_login_enabled": true, }, } if client.SupportsHeadlessLogin() { t.Fatalf("expected headless login prerequisites to be missing") } if client.IsHeadlessLoginEnabled() { t.Fatalf("expected headless login disabled when prerequisites are missing") } }) t.Run("headless login client without boolean metadata flag is not enabled", func(t *testing.T) { client := HydraClient{ TokenEndpointAuthMethod: "private_key_jwt", JWKSUri: "https://rp.example.com/.well-known/jwks.json", Metadata: map[string]any{ "headless_login_enabled": "true", }, } if !client.SupportsHeadlessLogin() { t.Fatalf("expected headless login client") } if client.IsHeadlessLoginEnabled() { t.Fatalf("expected headless login disabled for non-bool metadata") } }) } func TestHydraClientHeadlessMetadataAccessors(t *testing.T) { t.Run("metadata values override inline values", func(t *testing.T) { metadataJWKS := map[string]any{"keys": []any{"metadata-key"}} client := HydraClient{ TokenEndpointAuthMethod: "client_secret_post", JWKSUri: "https://inline.example.com/jwks.json", JWKS: map[string]any{"keys": []any{"inline-key"}}, Metadata: map[string]any{ MetadataHeadlessTokenEndpointAuthMethod: " private_key_jwt ", MetadataHeadlessJWKSURI: " https://metadata.example.com/jwks.json ", MetadataHeadlessJWKS: metadataJWKS, }, } if got := client.HeadlessTokenEndpointAuthMethod(); got != "private_key_jwt" { t.Fatalf("unexpected auth method: %q", got) } if got := client.HeadlessJWKSURI(); got != "https://metadata.example.com/jwks.json" { t.Fatalf("unexpected jwks uri: %q", got) } if got := client.HeadlessJWKS(); !reflect.DeepEqual(got, metadataJWKS) { t.Fatalf("unexpected jwks value: %#v", got) } }) t.Run("blank or missing metadata values fall back to inline values", func(t *testing.T) { inlineJWKS := map[string]any{"keys": []any{"inline-key"}} client := HydraClient{ TokenEndpointAuthMethod: " private_key_jwt ", JWKSUri: " https://inline.example.com/jwks.json ", JWKS: inlineJWKS, Metadata: map[string]any{ MetadataHeadlessTokenEndpointAuthMethod: " ", MetadataHeadlessJWKSURI: " ", MetadataHeadlessJWKS: nil, }, } if got := client.HeadlessTokenEndpointAuthMethod(); got != "private_key_jwt" { t.Fatalf("unexpected auth method: %q", got) } if got := client.HeadlessJWKSURI(); got != "https://inline.example.com/jwks.json" { t.Fatalf("unexpected jwks uri: %q", got) } if got := client.HeadlessJWKS(); !reflect.DeepEqual(got, inlineJWKS) { t.Fatalf("unexpected jwks value: %#v", got) } }) } func TestHydraClientBackchannelLogoutAccessors(t *testing.T) { t.Run("metadata values override inline values", func(t *testing.T) { inlineRequired := false client := HydraClient{ BackChannelLogoutURI: "https://inline.example.com/logout", BackChannelLogoutSessionRequired: &inlineRequired, Metadata: map[string]any{ MetadataBackChannelLogoutURI: " https://metadata.example.com/logout ", MetadataBackChannelLogoutSessionRequired: true, }, } if got := client.BackchannelLogoutURI(); got != "https://metadata.example.com/logout" { t.Fatalf("unexpected logout uri: %q", got) } if !client.BackchannelLogoutSessionRequiredValue() { t.Fatalf("expected metadata session_required value") } }) t.Run("blank or missing metadata values fall back to inline values", func(t *testing.T) { inlineRequired := true client := HydraClient{ BackChannelLogoutURI: " https://inline.example.com/logout ", BackChannelLogoutSessionRequired: &inlineRequired, Metadata: map[string]any{ MetadataBackChannelLogoutURI: " ", MetadataBackChannelLogoutSessionRequired: "true", }, } if got := client.BackchannelLogoutURI(); got != "https://inline.example.com/logout" { t.Fatalf("unexpected logout uri: %q", got) } if !client.BackchannelLogoutSessionRequiredValue() { t.Fatalf("expected inline session_required value") } }) t.Run("missing session required defaults to false", func(t *testing.T) { client := HydraClient{} if got := client.BackchannelLogoutURI(); got != "" { t.Fatalf("unexpected logout uri: %q", got) } if client.BackchannelLogoutSessionRequiredValue() { t.Fatalf("expected default session_required false") } }) }