diff --git a/saml_connection.go b/saml_connection.go index e274d10..af8b315 100644 --- a/saml_connection.go +++ b/saml_connection.go @@ -41,6 +41,7 @@ type SAMLConnection struct { AllowOrganizationAccountLinking bool `json:"allow_organization_account_linking"` CustomAttributes *[]CustomAttribute `json:"custom_attributes,omitempty"` Authenticatable bool `json:"authenticatable"` + LoginHint *LoginHint `json:"login_hint,omitempty"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } @@ -52,6 +53,13 @@ type SAMLConnectionAttributeMapping struct { LastName string `json:"last_name"` } +// LoginHint describes the login hint a SAML connection sends to the identity +// provider when initiating a sign-in. +type LoginHint struct { + Mode string `json:"mode"` + Source *string `json:"source,omitempty"` +} + type SAMLConnectionList struct { APIResource SAMLConnections []*SAMLConnection `json:"data"` diff --git a/samlconnection/client.go b/samlconnection/client.go index 28ace05..d56799f 100644 --- a/samlconnection/client.go +++ b/samlconnection/client.go @@ -39,6 +39,13 @@ type AttributeMappingParams struct { LastName string `json:"last_name"` } +// LoginHintParams configures the login hint a SAML connection sends to the +// identity provider when initiating a sign-in. +type LoginHintParams struct { + Mode *string `json:"mode,omitempty"` + Source *string `json:"source,omitempty"` +} + type CreateParams struct { clerk.APIParams Name *string `json:"name,omitempty"` @@ -55,6 +62,7 @@ type CreateParams struct { AttributeMapping *AttributeMappingParams `json:"attribute_mapping,omitempty"` ForceAuthn *bool `json:"force_authn,omitempty"` DisableJITProvisioning *bool `json:"disable_jit_provisioning,omitempty"` + LoginHint *LoginHintParams `json:"login_hint,omitempty"` // CustomAttributes is an Experimental feature, not available for all customers. CustomAttributes *[]clerk.CustomAttribute `json:"custom_attributes,omitempty"` } @@ -123,6 +131,7 @@ type UpdateParams struct { DisableJITProvisioning *bool `json:"disable_jit_provisioning,omitempty"` ConsentVerifiedDomainsDeletion *bool `json:"consent_verified_domains_deletion,omitempty"` Authenticatable *bool `json:"authenticatable,omitempty"` + LoginHint *LoginHintParams `json:"login_hint,omitempty"` // CustomAttributes is an Experimental feature, not available for all customers. CustomAttributes *[]clerk.CustomAttribute `json:"custom_attributes,omitempty"` } diff --git a/samlconnection/client_test.go b/samlconnection/client_test.go index 4677350..a636d57 100644 --- a/samlconnection/client_test.go +++ b/samlconnection/client_test.go @@ -20,12 +20,14 @@ func TestSAMLConnectionClientCreate(t *testing.T) { domain := "example.com" provider := "saml_custom" forceAuthn := true + loginHintMode := "custom_attribute" + loginHintSource := "employee_id" config := &clerk.ClientConfig{} config.HTTPClient = &http.Client{ Transport: &clerktest.RoundTripper{ T: t, - In: json.RawMessage(fmt.Sprintf(`{"name":"%s","domain":"%s","provider":"%s","force_authn":%t}`, name, domain, provider, forceAuthn)), - Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s","domain":"%s","provider":"%s","force_authn":%t}`, id, name, domain, provider, forceAuthn)), + In: json.RawMessage(fmt.Sprintf(`{"name":"%s","domain":"%s","provider":"%s","force_authn":%t,"login_hint":{"mode":"%s","source":"%s"}}`, name, domain, provider, forceAuthn, loginHintMode, loginHintSource)), + Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s","domain":"%s","provider":"%s","force_authn":%t,"login_hint":{"mode":"%s","source":"%s"}}`, id, name, domain, provider, forceAuthn, loginHintMode, loginHintSource)), Method: http.MethodPost, Path: "/v1/saml_connections", }, @@ -36,6 +38,10 @@ func TestSAMLConnectionClientCreate(t *testing.T) { Domain: clerk.String(domain), Provider: clerk.String(provider), ForceAuthn: clerk.Bool(forceAuthn), + LoginHint: &LoginHintParams{ + Mode: clerk.String(loginHintMode), + Source: clerk.String(loginHintSource), + }, }) require.NoError(t, err) require.Equal(t, id, samlConnection.ID) @@ -44,6 +50,10 @@ func TestSAMLConnectionClientCreate(t *testing.T) { require.Equal(t, domain, samlConnection.Domain) require.Equal(t, provider, samlConnection.Provider) require.Equal(t, forceAuthn, samlConnection.ForceAuthn) + require.NotNil(t, samlConnection.LoginHint) + require.Equal(t, loginHintMode, samlConnection.LoginHint.Mode) + require.NotNil(t, samlConnection.LoginHint.Source) + require.Equal(t, loginHintSource, *samlConnection.LoginHint.Source) } // TestSAMLConnectionClientCreate_WithBothDomainAndDomains tests that the client can not create a SAML connection @@ -142,11 +152,12 @@ func TestSAMLConnectionClientGet(t *testing.T) { provider := "saml_custom" disableAdditionalIdentifications := true forceAuthn := false + loginHintMode := "off" config := &clerk.ClientConfig{} config.HTTPClient = &http.Client{ Transport: &clerktest.RoundTripper{ T: t, - Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s","domain":"%s","provider":"%s", "disable_additional_identifications": %t, "force_authn": %t, "enterprise_connection_id": "entconn_2abc123def456", "custom_attributes": [{"name": "custom_attribute_name", "key": "custom_attribute_key", "sso_path": "custom_attribute_sso_path", "scim_path": "custom_attribute_scim_path"}]}`, id, name, domain, provider, disableAdditionalIdentifications, forceAuthn)), + Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s","domain":"%s","provider":"%s", "disable_additional_identifications": %t, "force_authn": %t, "login_hint": {"mode": "%s"}, "enterprise_connection_id": "entconn_2abc123def456", "custom_attributes": [{"name": "custom_attribute_name", "key": "custom_attribute_key", "sso_path": "custom_attribute_sso_path", "scim_path": "custom_attribute_scim_path"}]}`, id, name, domain, provider, disableAdditionalIdentifications, forceAuthn, loginHintMode)), Method: http.MethodGet, Path: "/v1/saml_connections/" + id, }, @@ -161,6 +172,9 @@ func TestSAMLConnectionClientGet(t *testing.T) { require.Equal(t, provider, samlConnection.Provider) require.Equal(t, disableAdditionalIdentifications, samlConnection.DisableAdditionalIdentifications) require.Equal(t, forceAuthn, samlConnection.ForceAuthn) + require.NotNil(t, samlConnection.LoginHint) + require.Equal(t, loginHintMode, samlConnection.LoginHint.Mode) + require.Nil(t, samlConnection.LoginHint.Source) require.Equal(t, &[]clerk.CustomAttribute{ { Name: clerk.String("custom_attribute_name"), @@ -179,12 +193,13 @@ func TestSAMLConnectionClientUpdate(t *testing.T) { provider := "saml_custom" disableAdditionalIdentifications := true forceAuthn := true + loginHintMode := "email_address" config := &clerk.ClientConfig{} config.HTTPClient = &http.Client{ Transport: &clerktest.RoundTripper{ T: t, - In: json.RawMessage(fmt.Sprintf(`{"name":"%s", "disable_additional_identifications": %t, "organization_id": "", "force_authn": %t, "custom_attributes": [{"name": "custom_attribute_name", "key": "custom_attribute_key", "sso_path": "custom_attribute_sso_path", "scim_path": "custom_attribute_scim_path"}]}`, name, disableAdditionalIdentifications, forceAuthn)), - Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s","domain":"%s","provider":"%s","disable_additional_identifications": %t,"force_authn": %t, "enterprise_connection_id": null, "custom_attributes": [{"name": "custom_attribute_name", "key": "custom_attribute_key", "sso_path": "custom_attribute_sso_path", "scim_path": "custom_attribute_scim_path"}]}`, id, name, domain, provider, disableAdditionalIdentifications, forceAuthn)), + In: json.RawMessage(fmt.Sprintf(`{"name":"%s", "disable_additional_identifications": %t, "organization_id": "", "force_authn": %t, "login_hint": {"mode": "%s"}, "custom_attributes": [{"name": "custom_attribute_name", "key": "custom_attribute_key", "sso_path": "custom_attribute_sso_path", "scim_path": "custom_attribute_scim_path"}]}`, name, disableAdditionalIdentifications, forceAuthn, loginHintMode)), + Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s","domain":"%s","provider":"%s","disable_additional_identifications": %t,"force_authn": %t, "login_hint": {"mode": "%s"}, "enterprise_connection_id": null, "custom_attributes": [{"name": "custom_attribute_name", "key": "custom_attribute_key", "sso_path": "custom_attribute_sso_path", "scim_path": "custom_attribute_scim_path"}]}`, id, name, domain, provider, disableAdditionalIdentifications, forceAuthn, loginHintMode)), Method: http.MethodPatch, Path: "/v1/saml_connections/" + id, }, @@ -195,6 +210,9 @@ func TestSAMLConnectionClientUpdate(t *testing.T) { DisableAdditionalIdentifications: clerk.Bool(disableAdditionalIdentifications), OrganizationID: clerk.String(""), ForceAuthn: clerk.Bool(forceAuthn), + LoginHint: &LoginHintParams{ + Mode: clerk.String(loginHintMode), + }, CustomAttributes: &[]clerk.CustomAttribute{ { Name: clerk.String("custom_attribute_name"), @@ -217,6 +235,9 @@ func TestSAMLConnectionClientUpdate(t *testing.T) { require.Equal(t, name, samlConnection.Name) require.Equal(t, disableAdditionalIdentifications, samlConnection.DisableAdditionalIdentifications) require.Equal(t, forceAuthn, samlConnection.ForceAuthn) + require.NotNil(t, samlConnection.LoginHint) + require.Equal(t, loginHintMode, samlConnection.LoginHint.Mode) + require.Nil(t, samlConnection.LoginHint.Source) } func TestSAMLConnectionClientUpdate_DisableJITProvisioning(t *testing.T) {