stages/identification: add field for passwordless flow

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-12-23 18:27:00 +01:00
parent b6b0edb7ad
commit 5c5634830f
13 changed files with 394 additions and 43 deletions

View File

@ -151,7 +151,7 @@ class AuthenticatorValidateStageView(ChallengeStageView):
if not, we can skip this entire stage"""
user = self.get_pending_user()
stage: AuthenticatorValidateStage = self.executor.current_stage
if user:
if user and not user.is_anonymous:
challenges = self.get_device_challenges()
else:
if self.executor.flow.designation != FlowDesignation.AUTHENTICATION:

View File

@ -19,6 +19,7 @@ class IdentificationStageSerializer(StageSerializer):
"show_matched_user",
"enrollment_flow",
"recovery_flow",
"passwordless_flow",
"sources",
"show_source_labels",
]
@ -36,6 +37,7 @@ class IdentificationStageViewSet(UsedByMixin, ModelViewSet):
"show_matched_user",
"enrollment_flow",
"recovery_flow",
"passwordless_flow",
"show_source_labels",
]
ordering = ["name"]

View File

@ -0,0 +1,172 @@
# Generated by Django 4.0 on 2021-12-23 17:12
import django.contrib.postgres.fields
import django.db.models.deletion
from django.apps.registry import Apps
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def assign_sources(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
db_alias = schema_editor.connection.alias
IdentificationStage = apps.get_model("authentik_stages_identification", "identificationstage")
Source = apps.get_model("authentik_core", "source")
sources = Source.objects.all()
for stage in IdentificationStage.objects.all().using(db_alias):
stage.sources.set(sources)
stage.save()
class Migration(migrations.Migration):
replaces = [
("authentik_stages_identification", "0002_auto_20200530_2204"),
("authentik_stages_identification", "0003_auto_20200615_1641"),
("authentik_stages_identification", "0004_identificationstage_case_insensitive_matching"),
("authentik_stages_identification", "0005_auto_20201003_1734"),
("authentik_stages_identification", "0006_identificationstage_show_matched_user"),
("authentik_stages_identification", "0007_remove_identificationstage_template"),
("authentik_stages_identification", "0008_alter_identificationstage_user_fields"),
("authentik_stages_identification", "0009_identificationstage_sources"),
("authentik_stages_identification", "0010_identificationstage_password_stage"),
("authentik_stages_identification", "0011_alter_identificationstage_user_fields"),
("authentik_stages_identification", "0012_identificationstage_show_source_labels"),
("authentik_stages_identification", "0013_identificationstage_passwordless_flow"),
]
dependencies = [
("authentik_stages_identification", "0001_initial"),
("authentik_core", "0021_alter_application_slug"),
("authentik_flows", "0003_auto_20200523_1133"),
("authentik_stages_password", "0005_auto_20210402_2221"),
("authentik_flows", "0007_auto_20200703_2059"),
("authentik_flows", "0020_flowtoken"),
]
operations = [
migrations.AddField(
model_name="identificationstage",
name="enrollment_flow",
field=models.ForeignKey(
blank=True,
default=None,
help_text="Optional enrollment flow, which is linked at the bottom of the page.",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
related_name="+",
to="authentik_flows.flow",
),
),
migrations.AddField(
model_name="identificationstage",
name="recovery_flow",
field=models.ForeignKey(
blank=True,
default=None,
help_text="Optional recovery flow, which is linked at the bottom of the page.",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
related_name="+",
to="authentik_flows.flow",
),
),
migrations.AddField(
model_name="identificationstage",
name="case_insensitive_matching",
field=models.BooleanField(
default=True,
help_text="When enabled, user fields are matched regardless of their casing.",
),
),
migrations.AlterField(
model_name="identificationstage",
name="user_fields",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.CharField(
choices=[("email", "E Mail"), ("username", "Username")], max_length=100
),
help_text="Fields of the user object to match against. (Hold shift to select multiple options)",
size=None,
),
),
migrations.AddField(
model_name="identificationstage",
name="show_matched_user",
field=models.BooleanField(
default=True,
help_text="When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown",
),
),
migrations.RemoveField(
model_name="identificationstage",
name="template",
),
migrations.AlterField(
model_name="identificationstage",
name="user_fields",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.CharField(
choices=[("email", "E Mail"), ("username", "Username")], max_length=100
),
blank=True,
help_text="Fields of the user object to match against. (Hold shift to select multiple options)",
size=None,
),
),
migrations.AddField(
model_name="identificationstage",
name="sources",
field=models.ManyToManyField(
default=list,
help_text="Specify which sources should be shown.",
to="authentik_core.Source",
),
),
migrations.RunPython(
code=assign_sources,
),
migrations.AddField(
model_name="identificationstage",
name="password_stage",
field=models.ForeignKey(
default=None,
help_text="When set, shows a password field, instead of showing the password field as seaprate step.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="authentik_stages_password.passwordstage",
),
),
migrations.AlterField(
model_name="identificationstage",
name="user_fields",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.CharField(
choices=[("email", "E Mail"), ("username", "Username"), ("upn", "Upn")],
max_length=100,
),
blank=True,
help_text="Fields of the user object to match against. (Hold shift to select multiple options)",
size=None,
),
),
migrations.AddField(
model_name="identificationstage",
name="show_source_labels",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="identificationstage",
name="passwordless_flow",
field=models.ForeignKey(
blank=True,
default=None,
help_text="Optional passwordless flow, which is linked at the bottom of the page.",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
related_name="+",
to="authentik_flows.flow",
),
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 4.0 on 2021-12-23 17:10
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0020_flowtoken"),
("authentik_stages_identification", "0012_identificationstage_show_source_labels"),
]
operations = [
migrations.AddField(
model_name="identificationstage",
name="passwordless_flow",
field=models.ForeignKey(
blank=True,
default=None,
help_text="Optional passwordless flow, which is linked at the bottom of the page.",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
related_name="+",
to="authentik_flows.flow",
),
),
]

View File

@ -77,6 +77,15 @@ class IdentificationStage(Stage):
default=None,
help_text=_("Optional recovery flow, which is linked at the bottom of the page."),
)
passwordless_flow = models.ForeignKey(
Flow,
on_delete=models.SET_DEFAULT,
null=True,
blank=True,
related_name="+",
default=None,
help_text=_("Optional passwordless flow, which is linked at the bottom of the page."),
)
sources = models.ManyToManyField(
Source, default=list, help_text=_("Specify which sources should be shown.")

View File

@ -68,6 +68,7 @@ class IdentificationChallenge(Challenge):
enroll_url = CharField(required=False)
recovery_url = CharField(required=False)
passwordless_url = CharField(required=False)
primary_action = CharField()
sources = LoginSourceSerializer(many=True, required=False)
show_source_labels = BooleanField()
@ -195,6 +196,11 @@ class IdentificationStageView(ChallengeStageView):
"authentik_core:if-flow",
kwargs={"flow_slug": current_stage.recovery_flow.slug},
)
if current_stage.passwordless_flow:
challenge.initial_data["passwordless_url"] = reverse(
"authentik_core:if-flow",
kwargs={"flow_slug": current_stage.passwordless_flow.slug},
)
# Check all enabled source, add them if they have a UI Login button.
ui_sources = []

View File

@ -16790,6 +16790,11 @@ paths:
schema:
type: string
format: uuid
- in: query
name: passwordless_flow
schema:
type: string
format: uuid
- in: query
name: recovery_flow
schema:
@ -21942,6 +21947,8 @@ components:
type: string
recovery_url:
type: string
passwordless_url:
type: string
primary_action:
type: string
sources:
@ -22031,6 +22038,12 @@ components:
nullable: true
description: Optional recovery flow, which is linked at the bottom of the
page.
passwordless_flow:
type: string
format: uuid
nullable: true
description: Optional passwordless flow, which is linked at the bottom of
the page.
sources:
type: array
items:
@ -22089,6 +22102,12 @@ components:
nullable: true
description: Optional recovery flow, which is linked at the bottom of the
page.
passwordless_flow:
type: string
format: uuid
nullable: true
description: Optional passwordless flow, which is linked at the bottom of
the page.
sources:
type: array
items:
@ -27155,6 +27174,12 @@ components:
nullable: true
description: Optional recovery flow, which is linked at the bottom of the
page.
passwordless_flow:
type: string
format: uuid
nullable: true
description: Optional passwordless flow, which is linked at the bottom of
the page.
sources:
type: array
items:

View File

@ -244,7 +244,17 @@ export class IdentificationStage extends BaseStage<
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${this.challenge.primaryAction}
</button>
</div>`;
</div>
${this.challenge.passwordlessUrl
? html`<div class="pf-c-form__group pf-m-action">
<a
href=${this.challenge.passwordlessUrl}
class="pf-c-button pf-m-secondary pf-m-block"
>
${t`Use a security key`}
</a>
</div>`
: html``}`;
}
render(): TemplateResult {

View File

@ -249,8 +249,8 @@ msgid "Alert"
msgstr "Alert"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Algorithm used to sign the JWT Tokens."
msgstr "Algorithm used to sign the JWT Tokens."
#~ msgid "Algorithm used to sign the JWT Tokens."
#~ msgstr "Algorithm used to sign the JWT Tokens."
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Allow IDP-initiated logins"
@ -2005,6 +2005,7 @@ msgstr "Flow inspector"
#: src/pages/sources/oauth/OAuthSourceForm.ts
#: src/pages/sources/plex/PlexSourceForm.ts
#: src/pages/sources/saml/SAMLSourceForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Flow settings"
msgstr "Flow settings"
@ -2213,8 +2214,8 @@ msgid "Groups"
msgstr "Groups"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "HS256 (Symmetric Encryption)"
msgstr "HS256 (Symmetric Encryption)"
#~ msgid "HS256 (Symmetric Encryption)"
#~ msgstr "HS256 (Symmetric Encryption)"
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "HTTP-Basic Password Key"
@ -2505,12 +2506,16 @@ msgid "Issuer mode"
msgstr "Issuer mode"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "JWT Algorithm"
msgstr "JWT Algorithm"
#~ msgid "JWT Algorithm"
#~ msgstr "JWT Algorithm"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
msgstr "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
msgid "Key used to sign the tokens."
msgstr "Key used to sign the tokens."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
#~ msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
#~ msgstr "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Keypair which is used to sign outgoing requests. Leave empty to disable signing."
@ -2700,6 +2705,7 @@ msgstr "Loading"
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/invitation/InvitationListLink.ts
#: src/pages/stages/password/PasswordStageForm.ts
#: src/pages/stages/prompt/PromptStageForm.ts
@ -3279,6 +3285,10 @@ msgstr "Optional data which is loaded into the flow's 'prompt_data' context vari
msgid "Optional enrollment flow, which is linked at the bottom of the page."
msgstr "Optional enrollment flow, which is linked at the bottom of the page."
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Optional passwordless flow, which is linked at the bottom of the page. When configured, users can use this flow to authenticate with a WebAuthn authenticator, without entering any details."
msgstr "Optional passwordless flow, which is linked at the bottom of the page. When configured, users can use this flow to authenticate with a WebAuthn authenticator, without entering any details."
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Optional recovery flow, which is linked at the bottom of the page."
msgstr "Optional recovery flow, which is linked at the bottom of the page."
@ -3420,6 +3430,10 @@ msgstr "Password stage"
msgid "Password: Masked input, password is validated against sources. Policies still have to be applied to this Stage. If two of these are used in the same stage, they are ensured to be identical."
msgstr "Password: Masked input, password is validated against sources. Policies still have to be applied to this Stage. If two of these are used in the same stage, they are ensured to be identical."
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Passwordless flow"
msgstr "Passwordless flow"
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Persistent"
msgstr "Persistent"
@ -3690,12 +3704,12 @@ msgid "RETRY returns the error message and a similar challenge to the executor."
msgstr "RETRY returns the error message and a similar challenge to the executor."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "RS256 (Asymmetric Encryption)"
msgstr "RS256 (Asymmetric Encryption)"
#~ msgid "RS256 (Asymmetric Encryption)"
#~ msgstr "RS256 (Asymmetric Encryption)"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "RSA Key"
msgstr "RSA Key"
#~ msgid "RSA Key"
#~ msgstr "RSA Key"
#: src/pages/providers/saml/SAMLProviderForm.ts
#: src/pages/sources/saml/SAMLSourceForm.ts
@ -4260,6 +4274,10 @@ msgstr "Signature algorithm"
msgid "Signing Certificate"
msgstr "Signing Certificate"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Signing Key"
msgstr "Signing Key"
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Signing keypair"
msgstr "Signing keypair"
@ -5487,6 +5505,10 @@ msgstr "Use TLS"
msgid "Use a code-based authenticator."
msgstr "Use a code-based authenticator."
#: src/flows/stages/identification/IdentificationStage.ts
msgid "Use a security key"
msgstr "Use a security key"
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
msgid "Use a security key to prove your identity."
msgstr "Use a security key to prove your identity."

View File

@ -253,8 +253,8 @@ msgid "Alert"
msgstr "Alerte"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Algorithm used to sign the JWT Tokens."
msgstr "Algorithme de signature utilisé pour les jetons JWT"
#~ msgid "Algorithm used to sign the JWT Tokens."
#~ msgstr "Algorithme de signature utilisé pour les jetons JWT"
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Allow IDP-initiated logins"
@ -1990,6 +1990,7 @@ msgstr "Inspecteur de flux"
#: src/pages/sources/oauth/OAuthSourceForm.ts
#: src/pages/sources/plex/PlexSourceForm.ts
#: src/pages/sources/saml/SAMLSourceForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Flow settings"
msgstr "Paramètres du flux"
@ -2196,8 +2197,8 @@ msgid "Groups"
msgstr "Groupes"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "HS256 (Symmetric Encryption)"
msgstr "HS256 (chiffrement symétrique)"
#~ msgid "HS256 (Symmetric Encryption)"
#~ msgstr "HS256 (chiffrement symétrique)"
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "HTTP-Basic Password Key"
@ -2485,12 +2486,16 @@ msgid "Issuer mode"
msgstr "Mode de l'émetteur"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "JWT Algorithm"
msgstr "Algorithme JWT"
#~ msgid "JWT Algorithm"
#~ msgstr "Algorithme JWT"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
msgstr "Clé utilisée pour signer les jetons. Nécessaire uniquement lorsque l'algorithme JWT est réglé sur RS256."
msgid "Key used to sign the tokens."
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
#~ msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
#~ msgstr "Clé utilisée pour signer les jetons. Nécessaire uniquement lorsque l'algorithme JWT est réglé sur RS256."
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Keypair which is used to sign outgoing requests. Leave empty to disable signing."
@ -2679,6 +2684,7 @@ msgstr "Chargement en cours"
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/invitation/InvitationListLink.ts
#: src/pages/stages/password/PasswordStageForm.ts
#: src/pages/stages/prompt/PromptStageForm.ts
@ -3254,6 +3260,10 @@ msgstr "Données optionnelles chargées dans la variable contextuelle 'prompt_da
msgid "Optional enrollment flow, which is linked at the bottom of the page."
msgstr "Flux d'inscription facultatif, qui sera accessible en bas de page."
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Optional passwordless flow, which is linked at the bottom of the page. When configured, users can use this flow to authenticate with a WebAuthn authenticator, without entering any details."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Optional recovery flow, which is linked at the bottom of the page."
msgstr "Flux de récupération facultatif, qui sera accessible en bas de page."
@ -3392,6 +3402,10 @@ msgstr "Étape de mot de passe"
msgid "Password: Masked input, password is validated against sources. Policies still have to be applied to this Stage. If two of these are used in the same stage, they are ensured to be identical."
msgstr "Mot de passe : Entrée masquée, le mot de passe est vérifié par les sources. Les politiques doivent encore être appliquées à cette étape. Si deux d'entre elles sont utilisées dans la même étape, on s'assure qu'elles sont identiques."
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Passwordless flow"
msgstr ""
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Persistent"
msgstr "Persistant"
@ -3658,12 +3672,12 @@ msgid "RETRY returns the error message and a similar challenge to the executor."
msgstr "RETRY indiquer le message d'erreur et présenter un challenge similaire à l'utilisateur"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "RS256 (Asymmetric Encryption)"
msgstr "RS256 (chiffrement asymétrique)"
#~ msgid "RS256 (Asymmetric Encryption)"
#~ msgstr "RS256 (chiffrement asymétrique)"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "RSA Key"
msgstr "Clé RSA"
#~ msgid "RSA Key"
#~ msgstr "Clé RSA"
#: src/pages/providers/saml/SAMLProviderForm.ts
#: src/pages/sources/saml/SAMLSourceForm.ts
@ -4223,6 +4237,10 @@ msgstr "Algorithme de signature"
msgid "Signing Certificate"
msgstr "Certificat de signature"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Signing Key"
msgstr ""
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Signing keypair"
msgstr "Paire de clés de signature"
@ -5427,6 +5445,10 @@ msgstr "Utiliser TLS"
msgid "Use a code-based authenticator."
msgstr "Utiliser un authentifieur à code."
#: src/flows/stages/identification/IdentificationStage.ts
msgid "Use a security key"
msgstr ""
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
msgid "Use a security key to prove your identity."
msgstr "Utilisez une clé de sécurité pour prouver votre identité."

View File

@ -249,8 +249,8 @@ msgid "Alert"
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Algorithm used to sign the JWT Tokens."
msgstr ""
#~ msgid "Algorithm used to sign the JWT Tokens."
#~ msgstr ""
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Allow IDP-initiated logins"
@ -1997,6 +1997,7 @@ msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts
#: src/pages/sources/plex/PlexSourceForm.ts
#: src/pages/sources/saml/SAMLSourceForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Flow settings"
msgstr ""
@ -2205,8 +2206,8 @@ msgid "Groups"
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "HS256 (Symmetric Encryption)"
msgstr ""
#~ msgid "HS256 (Symmetric Encryption)"
#~ msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "HTTP-Basic Password Key"
@ -2495,12 +2496,16 @@ msgid "Issuer mode"
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "JWT Algorithm"
#~ msgid "JWT Algorithm"
#~ msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Key used to sign the tokens."
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
msgstr ""
#~ msgid "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256."
#~ msgstr ""
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Keypair which is used to sign outgoing requests. Leave empty to disable signing."
@ -2690,6 +2695,7 @@ msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/invitation/InvitationListLink.ts
#: src/pages/stages/password/PasswordStageForm.ts
#: src/pages/stages/prompt/PromptStageForm.ts
@ -3269,6 +3275,10 @@ msgstr ""
msgid "Optional enrollment flow, which is linked at the bottom of the page."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Optional passwordless flow, which is linked at the bottom of the page. When configured, users can use this flow to authenticate with a WebAuthn authenticator, without entering any details."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Optional recovery flow, which is linked at the bottom of the page."
msgstr ""
@ -3410,6 +3420,10 @@ msgstr ""
msgid "Password: Masked input, password is validated against sources. Policies still have to be applied to this Stage. If two of these are used in the same stage, they are ensured to be identical."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "Passwordless flow"
msgstr ""
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Persistent"
msgstr ""
@ -3680,12 +3694,12 @@ msgid "RETRY returns the error message and a similar challenge to the executor."
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "RS256 (Asymmetric Encryption)"
msgstr ""
#~ msgid "RS256 (Asymmetric Encryption)"
#~ msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "RSA Key"
msgstr ""
#~ msgid "RSA Key"
#~ msgstr ""
#: src/pages/providers/saml/SAMLProviderForm.ts
#: src/pages/sources/saml/SAMLSourceForm.ts
@ -4250,6 +4264,10 @@ msgstr ""
msgid "Signing Certificate"
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "Signing Key"
msgstr ""
#: src/pages/sources/saml/SAMLSourceForm.ts
msgid "Signing keypair"
msgstr ""
@ -5467,6 +5485,10 @@ msgstr ""
msgid "Use a code-based authenticator."
msgstr ""
#: src/flows/stages/identification/IdentificationStage.ts
msgid "Use a security key"
msgstr ""
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
msgid "Use a security key to prove your identity."
msgstr ""

View File

@ -217,6 +217,44 @@ export class IdentificationStageForm extends ModelForm<IdentificationStage, stri
${t`When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown.`}
</p>
</ak-form-element-horizontal>
</ak-form-group>
<ak-form-group>
<span slot="header">${t`Flow settings`}</span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Passwordless flow`} name="passwordlessFlow">
<select class="pf-c-form-control">
<option
value=""
?selected=${this.instance?.passwordlessFlow === undefined}
>
---------
</option>
${until(
new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesList({
ordering: "slug",
designation:
FlowsInstancesListDesignationEnum.Authentication,
})
.then((flows) => {
return flows.results.map((flow) => {
const selected =
this.instance?.passwordlessFlow === flow.pk;
return html`<option
value=${ifDefined(flow.pk)}
?selected=${selected}
>
${flow.name} (${flow.slug})
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">
${t`Optional passwordless flow, which is linked at the bottom of the page. When configured, users can use this flow to authenticate with a WebAuthn authenticator, without entering any details.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Enrollment flow`} name="enrollmentFlow">
<select class="pf-c-form-control">
<option

View File

@ -32,12 +32,7 @@ As first stage, add an *Authentication validation* stage, with the WebAuthn devi
After this stage you can bind any additional verification stages.
As final stage, bind a *User login* stage.
This flow will return an error for users without a WebAuthn device. To circumvent this, you can add an identification and password stage
after the initial validation stage, and use a policy to skip them if the first stage already set a user. You can use a policy like this:
```python
return bool(request.user)
```
Users can either access this flow directly via it's URL, or you can modify any Identification stage to add a direct link to this flow.
#### Logging