stages/authenticator_webauthn: make user_verification configurable

closes #1921

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-12-14 09:58:20 +01:00
parent aa6b595545
commit 4e6714fffe
8 changed files with 133 additions and 6 deletions

View File

@ -18,7 +18,7 @@ class AuthenticateWebAuthnStageSerializer(StageSerializer):
class Meta:
model = AuthenticateWebAuthnStage
fields = StageSerializer.Meta.fields + ["configure_flow"]
fields = StageSerializer.Meta.fields + ["configure_flow", "user_verification"]
class AuthenticateWebAuthnStageViewSet(UsedByMixin, ModelViewSet):

View File

@ -9,15 +9,36 @@ from django.views import View
from django_otp.models import Device
from rest_framework.serializers import BaseSerializer
from webauthn.helpers.base64url_to_bytes import base64url_to_bytes
from webauthn.helpers.structs import PublicKeyCredentialDescriptor
from webauthn.helpers.structs import PublicKeyCredentialDescriptor, UserVerificationRequirement
from authentik.core.types import UserSettingSerializer
from authentik.flows.models import ConfigurableStage, Stage
class UserVerification(models.TextChoices):
"""The degree to which the Relying Party wishes to verify a user's identity.
Members:
`REQUIRED`: User verification must occur
`PREFERRED`: User verification would be great, but if not that's okay too
`DISCOURAGED`: User verification should not occur, but it's okay if it does
https://www.w3.org/TR/webauthn-2/#enumdef-userverificationrequirement
"""
REQUIRED = UserVerificationRequirement.REQUIRED
PREFERRED = UserVerificationRequirement.PREFERRED
DISCOURAGED = UserVerificationRequirement.DISCOURAGED
class AuthenticateWebAuthnStage(ConfigurableStage, Stage):
"""WebAuthn stage"""
user_verification = models.TextField(
choices=UserVerification.choices,
default=UserVerification.PREFERRED,
)
@property
def serializer(self) -> BaseSerializer:
from authentik.stages.authenticator_webauthn.api import AuthenticateWebAuthnStageSerializer

View File

@ -14,7 +14,6 @@ from webauthn.helpers.structs import (
PublicKeyCredentialCreationOptions,
RegistrationCredential,
ResidentKeyRequirement,
UserVerificationRequirement,
)
from webauthn.registration.verify_registration_response import VerifiedRegistration
@ -27,7 +26,7 @@ from authentik.flows.challenge import (
)
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
from authentik.flows.stage import ChallengeStageView
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage, WebAuthnDevice
from authentik.stages.authenticator_webauthn.utils import get_origin, get_rp_id
LOGGER = get_logger()
@ -83,7 +82,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
def get_challenge(self, *args, **kwargs) -> Challenge:
# clear session variables prior to starting a new registration
self.request.session.pop("challenge", None)
stage: AuthenticateWebAuthnStage = self.executor.current_stage
user = self.get_pending_user()
registration_options: PublicKeyCredentialCreationOptions = generate_registration_options(
@ -94,7 +93,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
user_display_name=user.name,
authenticator_selection=AuthenticatorSelectionCriteria(
resident_key=ResidentKeyRequirement.PREFERRED,
user_verification=UserVerificationRequirement.PREFERRED,
user_verification=str(stage.user_verification),
),
)
registration_options.user.id = user.uid

View File

@ -15395,6 +15395,14 @@ paths:
schema:
type: string
format: uuid
- in: query
name: user_verification
schema:
type: string
enum:
- discouraged
- preferred
- required
tags:
- stages
security:
@ -19240,6 +19248,8 @@ components:
nullable: true
description: Flow used by an authenticated user to configure this Stage.
If empty, user will not be able to configure this stage.
user_verification:
$ref: '#/components/schemas/UserVerificationEnum'
required:
- component
- meta_model_name
@ -19264,6 +19274,8 @@ components:
nullable: true
description: Flow used by an authenticated user to configure this Stage.
If empty, user will not be able to configure this stage.
user_verification:
$ref: '#/components/schemas/UserVerificationEnum'
required:
- name
AuthenticatedSession:
@ -26611,6 +26623,8 @@ components:
nullable: true
description: Flow used by an authenticated user to configure this Stage.
If empty, user will not be able to configure this stage.
user_verification:
$ref: '#/components/schemas/UserVerificationEnum'
PatchedAuthenticatorDuoStageRequest:
type: object
description: AuthenticatorDuoStage Serializer
@ -31235,6 +31249,12 @@ components:
- pk
- source
- user
UserVerificationEnum:
enum:
- required
- preferred
- discouraged
type: string
UserWriteStage:
type: object
description: UserWriteStage Serializer

View File

@ -4325,6 +4325,7 @@ msgstr "Stage(s)"
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/captcha/CaptchaStageForm.ts
#: src/pages/stages/consent/ConsentStageForm.ts
#: src/pages/stages/email/EmailStageForm.ts
@ -5510,6 +5511,22 @@ msgstr "User password writeback"
msgid "User status"
msgstr "User status"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification"
msgstr "User verification"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification is preferred if available, but not required."
msgstr "User verification is preferred if available, but not required."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification must occur."
msgstr "User verification must occur."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification should not occur."
msgstr "User verification should not occur."
#: src/pages/events/utils.ts
msgid "User was written to"
msgstr "User was written to"

View File

@ -4285,6 +4285,7 @@ msgstr "Étape(s)"
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/captcha/CaptchaStageForm.ts
#: src/pages/stages/consent/ConsentStageForm.ts
#: src/pages/stages/email/EmailStageForm.ts
@ -5448,6 +5449,22 @@ msgstr "Réécriture du mot de passe utilisateur"
msgid "User status"
msgstr "Statut utilisateur"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification is preferred if available, but not required."
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification must occur."
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification should not occur."
msgstr ""
#: src/pages/events/utils.ts
msgid "User was written to"
msgstr "L'utilisateur a été écrit vers "

View File

@ -4315,6 +4315,7 @@ msgstr ""
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/captcha/CaptchaStageForm.ts
#: src/pages/stages/consent/ConsentStageForm.ts
#: src/pages/stages/email/EmailStageForm.ts
@ -5490,6 +5491,22 @@ msgstr ""
msgid "User status"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification is preferred if available, but not required."
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification must occur."
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "User verification should not occur."
msgstr ""
#: src/pages/events/utils.ts
msgid "User was written to"
msgstr ""

View File

@ -1,3 +1,5 @@
import { UserVerificationEnum } from "@goauthentik/api/dist/models/UserVerificationEnum";
import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit";
@ -52,6 +54,40 @@ export class AuthenticateWebAuthnStageForm extends ModelForm<AuthenticateWebAuth
required
/>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}>
<span slot="header"> ${t`Stage-specific settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`User verification`}
?required=${true}
name="userVerification"
>
<select name="users" class="pf-c-form-control">
<option
value="${UserVerificationEnum.Required}"
?selected=${this.instance?.userVerification ===
UserVerificationEnum.Required}
>
${t`User verification must occur.`}
</option>
<option
value="${UserVerificationEnum.Preferred}"
?selected=${this.instance?.userVerification ===
UserVerificationEnum.Preferred}
>
${t`User verification is preferred if available, but not required.`}
</option>
<option
value="${UserVerificationEnum.Discouraged}"
?selected=${this.instance?.userVerification ===
UserVerificationEnum.Discouraged}
>
${t`User verification should not occur.`}
</option>
</select>
</ak-form-element-horizontal>
</div>
</ak-form-group>
</form>`;
}
}