Skip to content

Commit

Permalink
save raw aaguid on webauthn device
Browse files Browse the repository at this point in the history
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
  • Loading branch information
BeryJu committed Apr 18, 2024
1 parent e1d9707 commit 4d63fa2
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 2 deletions.
5 changes: 4 additions & 1 deletion authentik/stages/authenticator_webauthn/api/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ class WebAuthnDeviceSerializer(ModelSerializer):

class Meta:
model = WebAuthnDevice
fields = ["pk", "name", "created_on", "device_type"]
fields = ["pk", "name", "created_on", "device_type", "aaguid"]
extra_kwargs = {
"aaguid": {"read_only": True},
}


class WebAuthnDeviceViewSet(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# Generated by Django 5.0.4 on 2024-04-18 11:29

import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

replaces = [
("authentik_stages_authenticator_webauthn", "0001_initial"),
("authentik_stages_authenticator_webauthn", "0002_default_setup_flow"),
("authentik_stages_authenticator_webauthn", "0003_webauthndevice_confirmed"),
("authentik_stages_authenticator_webauthn", "0004_auto_20210304_1850"),
(
"authentik_stages_authenticator_webauthn",
"0005_authenticatewebauthnstage_user_verification",
),
(
"authentik_stages_authenticator_webauthn",
"0006_authenticatewebauthnstage_authenticator_attachment_and_more",
),
(
"authentik_stages_authenticator_webauthn",
"0007_rename_last_used_on_webauthndevice_last_t",
),
("authentik_stages_authenticator_webauthn", "0008_alter_webauthndevice_credential_id"),
("authentik_stages_authenticator_webauthn", "0009_authenticatewebauthnstage_friendly_name"),
(
"authentik_stages_authenticator_webauthn",
"0010_webauthndevicetype_authenticatorwebauthnstage_and_more",
),
("authentik_stages_authenticator_webauthn", "0011_webauthndevice_aaguid"),
]

initial = True

dependencies = [
("authentik_flows", "0016_auto_20201202_1307"),
("authentik_flows", "0027_auto_20231028_1424"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="WebAuthnDeviceType",
fields=[
("aaguid", models.UUIDField(primary_key=True, serialize=False, unique=True)),
("description", models.TextField()),
("icon", models.TextField(null=True)),
],
options={
"verbose_name": "WebAuthn Device type",
"verbose_name_plural": "WebAuthn Device types",
},
),
migrations.CreateModel(
name="AuthenticatorWebAuthnStage",
fields=[
(
"stage_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="authentik_flows.stage",
),
),
(
"configure_flow",
models.ForeignKey(
blank=True,
help_text="Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="authentik_flows.flow",
),
),
(
"user_verification",
models.TextField(
choices=[
("required", "Required"),
("preferred", "Preferred"),
("discouraged", "Discouraged"),
],
default="preferred",
),
),
(
"authenticator_attachment",
models.TextField(
choices=[("platform", "Platform"), ("cross-platform", "Cross Platform")],
default=None,
null=True,
),
),
(
"resident_key_requirement",
models.TextField(
choices=[
("discouraged", "Discouraged"),
("preferred", "Preferred"),
("required", "Required"),
],
default="preferred",
),
),
("friendly_name", models.TextField(null=True)),
(
"device_type_restrictions",
models.ManyToManyField(
blank=True, to="authentik_stages_authenticator_webauthn.webauthndevicetype"
),
),
],
options={
"verbose_name": "WebAuthn Authenticator Setup Stage",
"verbose_name_plural": "WebAuthn Authenticator Setup Stages",
},
bases=("authentik_flows.stage", models.Model),
),
migrations.CreateModel(
name="WebAuthnDevice",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.TextField(max_length=200)),
("credential_id", models.TextField(unique=True)),
("public_key", models.TextField()),
("sign_count", models.IntegerField(default=0)),
("rp_id", models.CharField(max_length=253)),
("created_on", models.DateTimeField(auto_now_add=True)),
("last_t", models.DateTimeField(default=django.utils.timezone.now)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
(
"confirmed",
models.BooleanField(default=True, help_text="Is this device ready for use?"),
),
(
"device_type",
models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
to="authentik_stages_authenticator_webauthn.webauthndevicetype",
),
),
("aaguid", models.TextField(default="00000000-0000-0000-0000-000000000000")),
],
options={
"verbose_name": "WebAuthn Device",
"verbose_name_plural": "WebAuthn Devices",
},
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 5.0.4 on 2024-04-18 11:27

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
(
"authentik_stages_authenticator_webauthn",
"0010_webauthndevicetype_authenticatorwebauthnstage_and_more",
),
]

operations = [
migrations.AddField(
model_name="webauthndevice",
name="aaguid",
field=models.TextField(default="00000000-0000-0000-0000-000000000000"),
),
]
1 change: 1 addition & 0 deletions authentik/stages/authenticator_webauthn/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class WebAuthnDevice(SerializerModel, Device):
created_on = models.DateTimeField(auto_now_add=True)
last_t = models.DateTimeField(default=now)

aaguid = models.TextField(default=UNKNOWN_DEVICE_TYPE_AAGUID)
device_type = models.ForeignKey(
"WebAuthnDeviceType", on_delete=models.SET_DEFAULT, null=True, default=None
)
Expand Down
1 change: 1 addition & 0 deletions authentik/stages/authenticator_webauthn/stage.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
sign_count=webauthn_credential.sign_count,
rp_id=get_rp_id(self.request),
device_type=device_type,
aaguid=webauthn_credential.aaguid,
)
else:
return self.executor.stage_invalid("Device with Credential ID already exists.")
Expand Down
2 changes: 1 addition & 1 deletion blueprints/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://goauthentik.io/blueprints/schema.json",
"type": "object",
"title": "authentik 2024.2.2 Blueprint schema",
"title": "authentik 2024.2.3 Blueprint schema",
"required": [
"version",
"entries"
Expand Down
24 changes: 24 additions & 0 deletions schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44714,6 +44714,26 @@ components:
- num_pk
- parent_name
- pk
UserGroupRequest:
type: object
description: Simplified Group Serializer for user's groups
properties:
name:
type: string
minLength: 1
maxLength: 80
is_superuser:
type: boolean
description: Users added to this group will be superusers.
parent:
type: string
format: uuid
nullable: true
attributes:
type: object
additionalProperties: {}
required:
- name
UserLoginChallenge:
type: object
description: Empty challenge
Expand Down Expand Up @@ -45400,7 +45420,11 @@ components:
- $ref: '#/components/schemas/WebAuthnDeviceType'
readOnly: true
nullable: true
aaguid:
type: string
readOnly: true
required:
- aaguid
- created_on
- device_type
- name
Expand Down

0 comments on commit 4d63fa2

Please sign in to comment.