source/saml: Add forceauthn to saml authnrequest (#20883)

* source/saml: Add ForceAuthn support to SAML AuthnRequest
This commit is contained in:
Connor Peshek
2026-03-31 22:54:01 -05:00
committed by GitHub
parent 1f872d1721
commit 8dddc05bc0
20 changed files with 264 additions and 0 deletions
+2
View File
@@ -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",
@@ -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.",
),
),
]
+6
View File
@@ -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,
@@ -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())
@@ -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")
+5
View File
@@ -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": [
+9
View File
@@ -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", "")
}
+38
View File
@@ -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")
+38
View File
@@ -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")
+38
View File
@@ -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")
+5
View File
@@ -7643,6 +7643,7 @@ pub async fn sources_saml_list(
digest_algorithm: Option<models::DigestAlgorithmEnum>,
enabled: Option<bool>,
enrollment_flow: Option<&str>,
force_authn: Option<bool>,
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", &param_value.to_string())]);
}
if let Some(ref param_value) = p_query_force_authn {
req_builder = req_builder.query(&[("force_authn", &param_value.to_string())]);
}
if let Some(ref param_value) = p_query_issuer {
req_builder = req_builder.query(&[("issuer", &param_value.to_string())]);
}
@@ -94,6 +94,9 @@ pub struct PatchedSamlSourceRequest {
skip_serializing_if = "Option::is_none"
)]
pub allow_idp_initiated: Option<bool>,
/// 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<bool>,
/// 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<models::SamlNameIdPolicyEnum>,
@@ -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,
+4
View File
@@ -114,6 +114,9 @@ pub struct SamlSource {
skip_serializing_if = "Option::is_none"
)]
pub allow_idp_initiated: Option<bool>,
/// 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<bool>,
/// 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<models::SamlNameIdPolicyEnum>,
@@ -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,
+4
View File
@@ -91,6 +91,9 @@ pub struct SamlSourceRequest {
skip_serializing_if = "Option::is_none"
)]
pub allow_idp_initiated: Option<bool>,
/// 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<bool>,
/// 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<models::SamlNameIdPolicyEnum>,
@@ -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,
+5
View File
@@ -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'];
}
@@ -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'],
+8
View File
@@ -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<SAMLSource, 'pk'|'component'|
'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'],
+8
View File
@@ -177,6 +177,12 @@ export interface SAMLSourceRequest {
* @memberof SAMLSourceRequest
*/
allowIdpInitiated?: boolean;
/**
* When enabled, the IdP will re-authenticate the user even if a session exists.
* @type {boolean}
* @memberof SAMLSourceRequest
*/
forceAuthn?: boolean;
/**
* NameID Policy sent to the IdP. Can be unset, in which case no Policy is sent.
* @type {SAMLNameIDPolicyEnum}
@@ -280,6 +286,7 @@ export function SAMLSourceRequestFromJSONTyped(json: any, ignoreDiscriminator: b
'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'],
@@ -322,6 +329,7 @@ export function SAMLSourceRequestToJSONTyped(value?: SAMLSourceRequest | null, i
'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'],
+16
View File
@@ -24087,6 +24087,10 @@ paths:
schema:
type: string
format: uuid
- in: query
name: force_authn
schema:
type: boolean
- in: query
name: issuer
schema:
@@ -50024,6 +50028,10 @@ components:
type: boolean
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
description: When enabled, the IdP will re-authenticate the user even if
a session exists.
name_id_policy:
allOf:
- $ref: '#/components/schemas/SAMLNameIDPolicyEnum'
@@ -53739,6 +53747,10 @@ components:
type: boolean
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
description: When enabled, the IdP will re-authenticate the user even if
a session exists.
name_id_policy:
allOf:
- $ref: '#/components/schemas/SAMLNameIDPolicyEnum'
@@ -53939,6 +53951,10 @@ components:
type: boolean
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
description: When enabled, the IdP will re-authenticate the user even if
a session exists.
name_id_policy:
allOf:
- $ref: '#/components/schemas/SAMLNameIDPolicyEnum'
@@ -303,6 +303,14 @@ export class SAMLSourceForm extends BaseSourceForm<SAMLSource> {
"Allows authentication flows initiated by the IdP. This can be a security risk, as no validation of the request ID is done.",
)}
></ak-switch-input>
<ak-switch-input
name="forceAuthn"
label=${msg("Force authentication")}
?checked=${!!this.instance?.forceAuthn}
help=${msg(
"When enabled, the IdP is requested to force re-authentication of the user, even if the user has an existing session.",
)}
></ak-switch-input>
<ak-form-element-horizontal
label=${msg("NameID Policy")}
required