From 5c5634830f6a4edd8580893a767fab041bb7f2b2 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 23 Dec 2021 18:27:00 +0100 Subject: [PATCH] stages/identification: add field for passwordless flow Signed-off-by: Jens Langhammer --- .../stages/authenticator_validate/stage.py | 2 +- authentik/stages/identification/api.py | 2 + ...3_identificationstage_passwordless_flow.py | 172 ++++++++++++++++++ ...3_identificationstage_passwordless_flow.py | 28 +++ authentik/stages/identification/models.py | 9 + authentik/stages/identification/stage.py | 6 + schema.yml | 25 +++ .../identification/IdentificationStage.ts | 12 +- web/src/locales/en.po | 46 +++-- web/src/locales/fr_FR.po | 46 +++-- web/src/locales/pseudo-LOCALE.po | 44 +++-- .../identification/IdentificationStageForm.ts | 38 ++++ .../stages/authenticator_validate/index.md | 7 +- 13 files changed, 394 insertions(+), 43 deletions(-) create mode 100644 authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py create mode 100644 authentik/stages/identification/migrations/0013_identificationstage_passwordless_flow.py diff --git a/authentik/stages/authenticator_validate/stage.py b/authentik/stages/authenticator_validate/stage.py index 000ac130e..b16b8d340 100644 --- a/authentik/stages/authenticator_validate/stage.py +++ b/authentik/stages/authenticator_validate/stage.py @@ -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: diff --git a/authentik/stages/identification/api.py b/authentik/stages/identification/api.py index 54925e1f7..5b3f8450c 100644 --- a/authentik/stages/identification/api.py +++ b/authentik/stages/identification/api.py @@ -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"] diff --git a/authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py b/authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py new file mode 100644 index 000000000..dd0721bf4 --- /dev/null +++ b/authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py @@ -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", + ), + ), + ] diff --git a/authentik/stages/identification/migrations/0013_identificationstage_passwordless_flow.py b/authentik/stages/identification/migrations/0013_identificationstage_passwordless_flow.py new file mode 100644 index 000000000..6333cbd6d --- /dev/null +++ b/authentik/stages/identification/migrations/0013_identificationstage_passwordless_flow.py @@ -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", + ), + ), + ] diff --git a/authentik/stages/identification/models.py b/authentik/stages/identification/models.py index 9f1127fbc..57417fb9e 100644 --- a/authentik/stages/identification/models.py +++ b/authentik/stages/identification/models.py @@ -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.") diff --git a/authentik/stages/identification/stage.py b/authentik/stages/identification/stage.py index 97f8a6c06..1379d69c6 100644 --- a/authentik/stages/identification/stage.py +++ b/authentik/stages/identification/stage.py @@ -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 = [] diff --git a/schema.yml b/schema.yml index aa6cba274..78ac85f86 100644 --- a/schema.yml +++ b/schema.yml @@ -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: diff --git a/web/src/flows/stages/identification/IdentificationStage.ts b/web/src/flows/stages/identification/IdentificationStage.ts index 9d8ad2c8a..4b1447bc2 100644 --- a/web/src/flows/stages/identification/IdentificationStage.ts +++ b/web/src/flows/stages/identification/IdentificationStage.ts @@ -244,7 +244,17 @@ export class IdentificationStage extends BaseStage< - `; + + ${this.challenge.passwordlessUrl + ? html`` + : html``}`; } render(): TemplateResult { diff --git a/web/src/locales/en.po b/web/src/locales/en.po index 33954dcb6..b715719d3 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -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." diff --git a/web/src/locales/fr_FR.po b/web/src/locales/fr_FR.po index d162856d9..3d0444707 100644 --- a/web/src/locales/fr_FR.po +++ b/web/src/locales/fr_FR.po @@ -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é." diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index 504787bfb..c91201f00 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -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 "" diff --git a/web/src/pages/stages/identification/IdentificationStageForm.ts b/web/src/pages/stages/identification/IdentificationStageForm.ts index 62333a0fc..4dd8fd95b 100644 --- a/web/src/pages/stages/identification/IdentificationStageForm.ts +++ b/web/src/pages/stages/identification/IdentificationStageForm.ts @@ -217,6 +217,44 @@ export class IdentificationStageForm extends ModelForm + + + ${t`Flow settings`} +
+ + +

+ ${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.`} +

+