From 8dddc05bc016ea6689d66ce208e822e2b3881ced Mon Sep 17 00:00:00 2001 From: Connor Peshek Date: Tue, 31 Mar 2026 22:54:01 -0500 Subject: [PATCH] source/saml: Add forceauthn to saml authnrequest (#20883) * source/saml: Add ForceAuthn support to SAML AuthnRequest --- authentik/sources/saml/api/source.py | 2 + .../migrations/0022_samlsource_force_authn.py | 21 ++++++++++ authentik/sources/saml/models.py | 6 +++ authentik/sources/saml/processors/request.py | 2 + authentik/sources/saml/tests/test_request.py | 35 +++++++++++++++++ blueprints/schema.json | 5 +++ packages/client-go/api_sources.go | 9 +++++ .../model_patched_saml_source_request.go | 38 +++++++++++++++++++ packages/client-go/model_saml_source.go | 38 +++++++++++++++++++ .../client-go/model_saml_source_request.go | 38 +++++++++++++++++++ packages/client-rust/src/apis/sources_api.rs | 5 +++ .../src/models/patched_saml_source_request.rs | 4 ++ .../client-rust/src/models/saml_source.rs | 4 ++ .../src/models/saml_source_request.rs | 4 ++ packages/client-ts/src/apis/SourcesApi.ts | 5 +++ .../src/models/PatchedSAMLSourceRequest.ts | 8 ++++ packages/client-ts/src/models/SAMLSource.ts | 8 ++++ .../client-ts/src/models/SAMLSourceRequest.ts | 8 ++++ schema.yml | 16 ++++++++ web/src/admin/sources/saml/SAMLSourceForm.ts | 8 ++++ 20 files changed, 264 insertions(+) create mode 100644 authentik/sources/saml/migrations/0022_samlsource_force_authn.py create mode 100644 authentik/sources/saml/tests/test_request.py diff --git a/authentik/sources/saml/api/source.py b/authentik/sources/saml/api/source.py index d327712981..b5bebef993 100644 --- a/authentik/sources/saml/api/source.py +++ b/authentik/sources/saml/api/source.py @@ -40,6 +40,7 @@ class SAMLSourceSerializer(SourceSerializer): "sso_url", "slo_url", "allow_idp_initiated", + "force_authn", "name_id_policy", "binding_type", "verification_kp", @@ -74,6 +75,7 @@ class SAMLSourceViewSet(UsedByMixin, ModelViewSet): "sso_url", "slo_url", "allow_idp_initiated", + "force_authn", "name_id_policy", "binding_type", "verification_kp", diff --git a/authentik/sources/saml/migrations/0022_samlsource_force_authn.py b/authentik/sources/saml/migrations/0022_samlsource_force_authn.py new file mode 100644 index 0000000000..06038cf1f3 --- /dev/null +++ b/authentik/sources/saml/migrations/0022_samlsource_force_authn.py @@ -0,0 +1,21 @@ +# Generated by Django 5.1.12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_sources_saml", "0021_samlsource_signed_assertion_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="samlsource", + name="force_authn", + field=models.BooleanField( + default=False, + help_text="When enabled, the IdP will re-authenticate the user even if a session exists.", + ), + ), + ] diff --git a/authentik/sources/saml/models.py b/authentik/sources/saml/models.py index fc4618d709..9401db9200 100644 --- a/authentik/sources/saml/models.py +++ b/authentik/sources/saml/models.py @@ -116,6 +116,12 @@ class SAMLSource(Source): "as no validation of the request ID is done." ), ) + force_authn = models.BooleanField( + default=False, + help_text=_( + "When enabled, the IdP will re-authenticate the user even if a session exists." + ), + ) name_id_policy = models.TextField( choices=SAMLNameIDPolicy.choices, default=SAMLNameIDPolicy.PERSISTENT, diff --git a/authentik/sources/saml/processors/request.py b/authentik/sources/saml/processors/request.py index 0c8bf4e962..2742e57e17 100644 --- a/authentik/sources/saml/processors/request.py +++ b/authentik/sources/saml/processors/request.py @@ -67,6 +67,8 @@ class RequestProcessor: auth_n_request.attrib["IssueInstant"] = self.issue_instant auth_n_request.attrib["ProtocolBinding"] = SAML_BINDING_POST auth_n_request.attrib["Version"] = "2.0" + if self.source.force_authn: + auth_n_request.attrib["ForceAuthn"] = "true" # Create issuer object auth_n_request.append(self.get_issuer()) diff --git a/authentik/sources/saml/tests/test_request.py b/authentik/sources/saml/tests/test_request.py new file mode 100644 index 0000000000..9e185d3af6 --- /dev/null +++ b/authentik/sources/saml/tests/test_request.py @@ -0,0 +1,35 @@ +"""SAML Source AuthnRequest tests""" + +from django.test import RequestFactory, TestCase + +from authentik.core.tests.utils import create_test_flow +from authentik.lib.generators import generate_id +from authentik.sources.saml.models import SAMLSource +from authentik.sources.saml.processors.request import RequestProcessor + + +class TestRequestProcessor(TestCase): + """Test SAML AuthnRequest generation""" + + def setUp(self): + self.factory = RequestFactory() + self.source = SAMLSource.objects.create( + name=generate_id(), + slug=generate_id(), + issuer="authentik", + sso_url="https://idp.example.com/sso", + pre_authentication_flow=create_test_flow(), + ) + + def test_force_authn_flag(self): + """Test that ForceAuthn attribute is set when force_authn is True""" + self.source.force_authn = True + self.source.save() + + request = self.factory.get("/") + request.session = {} + + processor = RequestProcessor(self.source, request, "") + auth_n = processor.get_auth_n() + + self.assertEqual(auth_n.attrib.get("ForceAuthn"), "true") diff --git a/blueprints/schema.json b/blueprints/schema.json index 4c4e8702c6..8abdfe81c8 100644 --- a/blueprints/schema.json +++ b/blueprints/schema.json @@ -13493,6 +13493,11 @@ "title": "Allow idp initiated", "description": "Allows authentication flows initiated by the IdP. This can be a security risk, as no validation of the request ID is done." }, + "force_authn": { + "type": "boolean", + "title": "Force authn", + "description": "When enabled, the IdP will re-authenticate the user even if a session exists." + }, "name_id_policy": { "type": "string", "enum": [ diff --git a/packages/client-go/api_sources.go b/packages/client-go/api_sources.go index 3765ed3cd1..4c1e47f80c 100644 --- a/packages/client-go/api_sources.go +++ b/packages/client-go/api_sources.go @@ -12595,6 +12595,7 @@ type ApiSourcesSamlListRequest struct { digestAlgorithm *DigestAlgorithmEnum enabled *bool enrollmentFlow *string + forceAuthn *bool issuer *string managed *string name *string @@ -12648,6 +12649,11 @@ func (r ApiSourcesSamlListRequest) EnrollmentFlow(enrollmentFlow string) ApiSour return r } +func (r ApiSourcesSamlListRequest) ForceAuthn(forceAuthn bool) ApiSourcesSamlListRequest { + r.forceAuthn = &forceAuthn + return r +} + func (r ApiSourcesSamlListRequest) Issuer(issuer string) ApiSourcesSamlListRequest { r.issuer = &issuer return r @@ -12816,6 +12822,9 @@ func (a *SourcesAPIService) SourcesSamlListExecute(r ApiSourcesSamlListRequest) if r.enrollmentFlow != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "enrollment_flow", r.enrollmentFlow, "form", "") } + if r.forceAuthn != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "force_authn", r.forceAuthn, "form", "") + } if r.issuer != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "issuer", r.issuer, "form", "") } diff --git a/packages/client-go/model_patched_saml_source_request.go b/packages/client-go/model_patched_saml_source_request.go index 2a09c2e063..4e4cd9cb89 100644 --- a/packages/client-go/model_patched_saml_source_request.go +++ b/packages/client-go/model_patched_saml_source_request.go @@ -50,6 +50,8 @@ type PatchedSAMLSourceRequest struct { SloUrl NullableString `json:"slo_url,omitempty"` // Allows authentication flows initiated by the IdP. This can be a security risk, as no validation of the request ID is done. AllowIdpInitiated *bool `json:"allow_idp_initiated,omitempty"` + // When enabled, the IdP will re-authenticate the user even if a session exists. + ForceAuthn *bool `json:"force_authn,omitempty"` // NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. NameIdPolicy *SAMLNameIDPolicyEnum `json:"name_id_policy,omitempty"` BindingType *BindingTypeEnum `json:"binding_type,omitempty"` @@ -696,6 +698,38 @@ func (o *PatchedSAMLSourceRequest) SetAllowIdpInitiated(v bool) { o.AllowIdpInitiated = &v } +// GetForceAuthn returns the ForceAuthn field value if set, zero value otherwise. +func (o *PatchedSAMLSourceRequest) GetForceAuthn() bool { + if o == nil || IsNil(o.ForceAuthn) { + var ret bool + return ret + } + return *o.ForceAuthn +} + +// GetForceAuthnOk returns a tuple with the ForceAuthn field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchedSAMLSourceRequest) GetForceAuthnOk() (*bool, bool) { + if o == nil || IsNil(o.ForceAuthn) { + return nil, false + } + return o.ForceAuthn, true +} + +// HasForceAuthn returns a boolean if a field has been set. +func (o *PatchedSAMLSourceRequest) HasForceAuthn() bool { + if o != nil && !IsNil(o.ForceAuthn) { + return true + } + + return false +} + +// SetForceAuthn gets a reference to the given bool and assigns it to the ForceAuthn field. +func (o *PatchedSAMLSourceRequest) SetForceAuthn(v bool) { + o.ForceAuthn = &v +} + // GetNameIdPolicy returns the NameIdPolicy field value if set, zero value otherwise. func (o *PatchedSAMLSourceRequest) GetNameIdPolicy() SAMLNameIDPolicyEnum { if o == nil || IsNil(o.NameIdPolicy) { @@ -1113,6 +1147,9 @@ func (o PatchedSAMLSourceRequest) ToMap() (map[string]interface{}, error) { if !IsNil(o.AllowIdpInitiated) { toSerialize["allow_idp_initiated"] = o.AllowIdpInitiated } + if !IsNil(o.ForceAuthn) { + toSerialize["force_authn"] = o.ForceAuthn + } if !IsNil(o.NameIdPolicy) { toSerialize["name_id_policy"] = o.NameIdPolicy } @@ -1183,6 +1220,7 @@ func (o *PatchedSAMLSourceRequest) UnmarshalJSON(data []byte) (err error) { delete(additionalProperties, "sso_url") delete(additionalProperties, "slo_url") delete(additionalProperties, "allow_idp_initiated") + delete(additionalProperties, "force_authn") delete(additionalProperties, "name_id_policy") delete(additionalProperties, "binding_type") delete(additionalProperties, "verification_kp") diff --git a/packages/client-go/model_saml_source.go b/packages/client-go/model_saml_source.go index d3c4d1ffc1..3728832683 100644 --- a/packages/client-go/model_saml_source.go +++ b/packages/client-go/model_saml_source.go @@ -64,6 +64,8 @@ type SAMLSource struct { SloUrl NullableString `json:"slo_url,omitempty"` // Allows authentication flows initiated by the IdP. This can be a security risk, as no validation of the request ID is done. AllowIdpInitiated *bool `json:"allow_idp_initiated,omitempty"` + // When enabled, the IdP will re-authenticate the user even if a session exists. + ForceAuthn *bool `json:"force_authn,omitempty"` // NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. NameIdPolicy *SAMLNameIDPolicyEnum `json:"name_id_policy,omitempty"` BindingType *BindingTypeEnum `json:"binding_type,omitempty"` @@ -886,6 +888,38 @@ func (o *SAMLSource) SetAllowIdpInitiated(v bool) { o.AllowIdpInitiated = &v } +// GetForceAuthn returns the ForceAuthn field value if set, zero value otherwise. +func (o *SAMLSource) GetForceAuthn() bool { + if o == nil || IsNil(o.ForceAuthn) { + var ret bool + return ret + } + return *o.ForceAuthn +} + +// GetForceAuthnOk returns a tuple with the ForceAuthn field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SAMLSource) GetForceAuthnOk() (*bool, bool) { + if o == nil || IsNil(o.ForceAuthn) { + return nil, false + } + return o.ForceAuthn, true +} + +// HasForceAuthn returns a boolean if a field has been set. +func (o *SAMLSource) HasForceAuthn() bool { + if o != nil && !IsNil(o.ForceAuthn) { + return true + } + + return false +} + +// SetForceAuthn gets a reference to the given bool and assigns it to the ForceAuthn field. +func (o *SAMLSource) SetForceAuthn(v bool) { + o.ForceAuthn = &v +} + // GetNameIdPolicy returns the NameIdPolicy field value if set, zero value otherwise. func (o *SAMLSource) GetNameIdPolicy() SAMLNameIDPolicyEnum { if o == nil || IsNil(o.NameIdPolicy) { @@ -1303,6 +1337,9 @@ func (o SAMLSource) ToMap() (map[string]interface{}, error) { if !IsNil(o.AllowIdpInitiated) { toSerialize["allow_idp_initiated"] = o.AllowIdpInitiated } + if !IsNil(o.ForceAuthn) { + toSerialize["force_authn"] = o.ForceAuthn + } if !IsNil(o.NameIdPolicy) { toSerialize["name_id_policy"] = o.NameIdPolicy } @@ -1413,6 +1450,7 @@ func (o *SAMLSource) UnmarshalJSON(data []byte) (err error) { delete(additionalProperties, "sso_url") delete(additionalProperties, "slo_url") delete(additionalProperties, "allow_idp_initiated") + delete(additionalProperties, "force_authn") delete(additionalProperties, "name_id_policy") delete(additionalProperties, "binding_type") delete(additionalProperties, "verification_kp") diff --git a/packages/client-go/model_saml_source_request.go b/packages/client-go/model_saml_source_request.go index 123106aa1e..8084c0d512 100644 --- a/packages/client-go/model_saml_source_request.go +++ b/packages/client-go/model_saml_source_request.go @@ -51,6 +51,8 @@ type SAMLSourceRequest struct { SloUrl NullableString `json:"slo_url,omitempty"` // Allows authentication flows initiated by the IdP. This can be a security risk, as no validation of the request ID is done. AllowIdpInitiated *bool `json:"allow_idp_initiated,omitempty"` + // When enabled, the IdP will re-authenticate the user even if a session exists. + ForceAuthn *bool `json:"force_authn,omitempty"` // NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. NameIdPolicy *SAMLNameIDPolicyEnum `json:"name_id_policy,omitempty"` BindingType *BindingTypeEnum `json:"binding_type,omitempty"` @@ -669,6 +671,38 @@ func (o *SAMLSourceRequest) SetAllowIdpInitiated(v bool) { o.AllowIdpInitiated = &v } +// GetForceAuthn returns the ForceAuthn field value if set, zero value otherwise. +func (o *SAMLSourceRequest) GetForceAuthn() bool { + if o == nil || IsNil(o.ForceAuthn) { + var ret bool + return ret + } + return *o.ForceAuthn +} + +// GetForceAuthnOk returns a tuple with the ForceAuthn field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SAMLSourceRequest) GetForceAuthnOk() (*bool, bool) { + if o == nil || IsNil(o.ForceAuthn) { + return nil, false + } + return o.ForceAuthn, true +} + +// HasForceAuthn returns a boolean if a field has been set. +func (o *SAMLSourceRequest) HasForceAuthn() bool { + if o != nil && !IsNil(o.ForceAuthn) { + return true + } + + return false +} + +// SetForceAuthn gets a reference to the given bool and assigns it to the ForceAuthn field. +func (o *SAMLSourceRequest) SetForceAuthn(v bool) { + o.ForceAuthn = &v +} + // GetNameIdPolicy returns the NameIdPolicy field value if set, zero value otherwise. func (o *SAMLSourceRequest) GetNameIdPolicy() SAMLNameIDPolicyEnum { if o == nil || IsNil(o.NameIdPolicy) { @@ -1078,6 +1112,9 @@ func (o SAMLSourceRequest) ToMap() (map[string]interface{}, error) { if !IsNil(o.AllowIdpInitiated) { toSerialize["allow_idp_initiated"] = o.AllowIdpInitiated } + if !IsNil(o.ForceAuthn) { + toSerialize["force_authn"] = o.ForceAuthn + } if !IsNil(o.NameIdPolicy) { toSerialize["name_id_policy"] = o.NameIdPolicy } @@ -1172,6 +1209,7 @@ func (o *SAMLSourceRequest) UnmarshalJSON(data []byte) (err error) { delete(additionalProperties, "sso_url") delete(additionalProperties, "slo_url") delete(additionalProperties, "allow_idp_initiated") + delete(additionalProperties, "force_authn") delete(additionalProperties, "name_id_policy") delete(additionalProperties, "binding_type") delete(additionalProperties, "verification_kp") diff --git a/packages/client-rust/src/apis/sources_api.rs b/packages/client-rust/src/apis/sources_api.rs index a0ef2e4529..1d72369b33 100644 --- a/packages/client-rust/src/apis/sources_api.rs +++ b/packages/client-rust/src/apis/sources_api.rs @@ -7643,6 +7643,7 @@ pub async fn sources_saml_list( digest_algorithm: Option, enabled: Option, enrollment_flow: Option<&str>, + force_authn: Option, issuer: Option<&str>, managed: Option<&str>, name: Option<&str>, @@ -7672,6 +7673,7 @@ pub async fn sources_saml_list( let p_query_digest_algorithm = digest_algorithm; let p_query_enabled = enabled; let p_query_enrollment_flow = enrollment_flow; + let p_query_force_authn = force_authn; let p_query_issuer = issuer; let p_query_managed = managed; let p_query_name = name; @@ -7715,6 +7717,9 @@ pub async fn sources_saml_list( if let Some(ref param_value) = p_query_enrollment_flow { req_builder = req_builder.query(&[("enrollment_flow", ¶m_value.to_string())]); } + if let Some(ref param_value) = p_query_force_authn { + req_builder = req_builder.query(&[("force_authn", ¶m_value.to_string())]); + } if let Some(ref param_value) = p_query_issuer { req_builder = req_builder.query(&[("issuer", ¶m_value.to_string())]); } diff --git a/packages/client-rust/src/models/patched_saml_source_request.rs b/packages/client-rust/src/models/patched_saml_source_request.rs index e79fd56f86..cb5ccfee2f 100644 --- a/packages/client-rust/src/models/patched_saml_source_request.rs +++ b/packages/client-rust/src/models/patched_saml_source_request.rs @@ -94,6 +94,9 @@ pub struct PatchedSamlSourceRequest { skip_serializing_if = "Option::is_none" )] pub allow_idp_initiated: Option, + /// When enabled, the IdP will re-authenticate the user even if a session exists. + #[serde(rename = "force_authn", skip_serializing_if = "Option::is_none")] + pub force_authn: Option, /// NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. #[serde(rename = "name_id_policy", skip_serializing_if = "Option::is_none")] pub name_id_policy: Option, @@ -168,6 +171,7 @@ impl PatchedSamlSourceRequest { sso_url: None, slo_url: None, allow_idp_initiated: None, + force_authn: None, name_id_policy: None, binding_type: None, verification_kp: None, diff --git a/packages/client-rust/src/models/saml_source.rs b/packages/client-rust/src/models/saml_source.rs index 34daa886bf..8926ef83fa 100644 --- a/packages/client-rust/src/models/saml_source.rs +++ b/packages/client-rust/src/models/saml_source.rs @@ -114,6 +114,9 @@ pub struct SamlSource { skip_serializing_if = "Option::is_none" )] pub allow_idp_initiated: Option, + /// When enabled, the IdP will re-authenticate the user even if a session exists. + #[serde(rename = "force_authn", skip_serializing_if = "Option::is_none")] + pub force_authn: Option, /// NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. #[serde(rename = "name_id_policy", skip_serializing_if = "Option::is_none")] pub name_id_policy: Option, @@ -209,6 +212,7 @@ impl SamlSource { sso_url, slo_url: None, allow_idp_initiated: None, + force_authn: None, name_id_policy: None, binding_type: None, verification_kp: None, diff --git a/packages/client-rust/src/models/saml_source_request.rs b/packages/client-rust/src/models/saml_source_request.rs index 499fb874d1..04a4af46b6 100644 --- a/packages/client-rust/src/models/saml_source_request.rs +++ b/packages/client-rust/src/models/saml_source_request.rs @@ -91,6 +91,9 @@ pub struct SamlSourceRequest { skip_serializing_if = "Option::is_none" )] pub allow_idp_initiated: Option, + /// When enabled, the IdP will re-authenticate the user even if a session exists. + #[serde(rename = "force_authn", skip_serializing_if = "Option::is_none")] + pub force_authn: Option, /// NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. #[serde(rename = "name_id_policy", skip_serializing_if = "Option::is_none")] pub name_id_policy: Option, @@ -170,6 +173,7 @@ impl SamlSourceRequest { sso_url, slo_url: None, allow_idp_initiated: None, + force_authn: None, name_id_policy: None, binding_type: None, verification_kp: None, diff --git a/packages/client-ts/src/apis/SourcesApi.ts b/packages/client-ts/src/apis/SourcesApi.ts index eda3b02c9f..8f8e66da72 100644 --- a/packages/client-ts/src/apis/SourcesApi.ts +++ b/packages/client-ts/src/apis/SourcesApi.ts @@ -864,6 +864,7 @@ export interface SourcesSamlListRequest { digestAlgorithm?: DigestAlgorithmEnum; enabled?: boolean; enrollmentFlow?: string; + forceAuthn?: boolean; issuer?: string; managed?: string; name?: string; @@ -6687,6 +6688,10 @@ export class SourcesApi extends runtime.BaseAPI { queryParameters['enrollment_flow'] = requestParameters['enrollmentFlow']; } + if (requestParameters['forceAuthn'] != null) { + queryParameters['force_authn'] = requestParameters['forceAuthn']; + } + if (requestParameters['issuer'] != null) { queryParameters['issuer'] = requestParameters['issuer']; } diff --git a/packages/client-ts/src/models/PatchedSAMLSourceRequest.ts b/packages/client-ts/src/models/PatchedSAMLSourceRequest.ts index 6570890360..354ed14d42 100644 --- a/packages/client-ts/src/models/PatchedSAMLSourceRequest.ts +++ b/packages/client-ts/src/models/PatchedSAMLSourceRequest.ts @@ -177,6 +177,12 @@ export interface PatchedSAMLSourceRequest { * @memberof PatchedSAMLSourceRequest */ allowIdpInitiated?: boolean; + /** + * When enabled, the IdP will re-authenticate the user even if a session exists. + * @type {boolean} + * @memberof PatchedSAMLSourceRequest + */ + forceAuthn?: boolean; /** * NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. * @type {SAMLNameIDPolicyEnum} @@ -276,6 +282,7 @@ export function PatchedSAMLSourceRequestFromJSONTyped(json: any, ignoreDiscrimin 'ssoUrl': json['sso_url'] == null ? undefined : json['sso_url'], 'sloUrl': json['slo_url'] == null ? undefined : json['slo_url'], 'allowIdpInitiated': json['allow_idp_initiated'] == null ? undefined : json['allow_idp_initiated'], + 'forceAuthn': json['force_authn'] == null ? undefined : json['force_authn'], 'nameIdPolicy': json['name_id_policy'] == null ? undefined : SAMLNameIDPolicyEnumFromJSON(json['name_id_policy']), 'bindingType': json['binding_type'] == null ? undefined : BindingTypeEnumFromJSON(json['binding_type']), 'verificationKp': json['verification_kp'] == null ? undefined : json['verification_kp'], @@ -318,6 +325,7 @@ export function PatchedSAMLSourceRequestToJSONTyped(value?: PatchedSAMLSourceReq 'sso_url': value['ssoUrl'], 'slo_url': value['sloUrl'], 'allow_idp_initiated': value['allowIdpInitiated'], + 'force_authn': value['forceAuthn'], 'name_id_policy': SAMLNameIDPolicyEnumToJSON(value['nameIdPolicy']), 'binding_type': BindingTypeEnumToJSON(value['bindingType']), 'verification_kp': value['verificationKp'], diff --git a/packages/client-ts/src/models/SAMLSource.ts b/packages/client-ts/src/models/SAMLSource.ts index ee9522a4c2..b93e4bb7f5 100644 --- a/packages/client-ts/src/models/SAMLSource.ts +++ b/packages/client-ts/src/models/SAMLSource.ts @@ -232,6 +232,12 @@ export interface SAMLSource { * @memberof SAMLSource */ allowIdpInitiated?: boolean; + /** + * When enabled, the IdP will re-authenticate the user even if a session exists. + * @type {boolean} + * @memberof SAMLSource + */ + forceAuthn?: boolean; /** * NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent. * @type {SAMLNameIDPolicyEnum} @@ -351,6 +357,7 @@ export function SAMLSourceFromJSONTyped(json: any, ignoreDiscriminator: boolean) 'ssoUrl': json['sso_url'], 'sloUrl': json['slo_url'] == null ? undefined : json['slo_url'], 'allowIdpInitiated': json['allow_idp_initiated'] == null ? undefined : json['allow_idp_initiated'], + 'forceAuthn': json['force_authn'] == null ? undefined : json['force_authn'], 'nameIdPolicy': json['name_id_policy'] == null ? undefined : SAMLNameIDPolicyEnumFromJSON(json['name_id_policy']), 'bindingType': json['binding_type'] == null ? undefined : BindingTypeEnumFromJSON(json['binding_type']), 'verificationKp': json['verification_kp'] == null ? undefined : json['verification_kp'], @@ -393,6 +400,7 @@ export function SAMLSourceToJSONTyped(value?: Omit { "Allows authentication flows initiated by the IdP. This can be a security risk, as no validation of the request ID is done.", )} > +