Repository: goauthentik/authentik

Issue:
WebAuthn Token (Solo v2) registration fails with `value too long` error
**Describe the bug**
When trying to register a WebAuthn token (SoloKey's Solo v2) as MFA device, the registration fails with the message `django.db.utils.DataError: value too long for type character varying(300)`.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to user settings
2. Go to sidebar menu point 'MFA Devices'
3. Click on 'Enroll'
4. Click on 'Security key authenticator'
5. (Windows client) Accept the system dialog, that an application would like to set up a security token
6. Enter device PIN
7. Authorize by touching (in this case) the security token
8. Observe error message. (*One note at this point: the error message is horribly unreadable. In the default zoom/size settings, the title is completely invisible, even with scrolling. Only reducing the zoom to 70% allows for the title above the stacktrace to be visible. I would suggest collapsing such tracebacks by default. Just my "2 cents"*)

**Expected behavior**
The token registration to complete without errors.

**Screenshots**
If applicable, add screenshots to help explain your problem.
<details>
  <summary>Screenshot: Almost unreadable error message at 50% browser zoom</summary>
  
![grafik](https://user-images.githubusercontent.com/24863329/224809957-e7dd2a02-bffd-4446-bde8-8a76e1dc503d.png)
</details>



**Logs**
The exception stacktrace, as displayed in the browser:
```
Traceback (most recent call last):
  File "/authentik/flows/views/executor.py", line 340, in post
    stage_response = self.current_stage_view.post(request, *args, **kwargs)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/flows/stage.py", line 137, in post
    return self.challenge_valid(challenge)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/stages/authenticator_webauthn/stage.py", line 128, in challenge_valid
    WebAuthnDevice.objects.create(
  File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 671, in create
    obj.save(force_insert=True, using=self.db)
  File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 812, in save
    self.save_base(
  File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 863, in save_base
    updated = self._save_table(
              ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1006, in _save_table
    results = self._do_insert(
              ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1047, in _do_insert
    return manager._insert(
           ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 1791, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1660, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.11/site-packages/sentry_sdk/integrations/django/__init__.py", line 578, in execute
    return real_execute(self, sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/usr/local/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django_prometheus/db/common.py", line 71, in execute
    return super().execute(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
django.db.utils.DataError: value too long for type character varying(300)
```


The logs from `docker compose logs`:
```
authentik-server-1      | {"auth_via": "session", "event": "/flows/-/configure/8063f4e4-9a12-4bee-8c24-1c4c7bc17464/?next=%2Fif%2Fuser%2F%23%2Fsettings%3B%7B%22page%22%3A%22page-mfa%22%7D", "host": "authentik.felix-ern.de", "level": "info", "logger": "authentik.asgi", "method": "GET", "pid": 21, "remote": "<CENSORED_IPV6>", "request_id": "c0ced0985392408f9f07657c80748d98", "runtime": 33, "scheme": "https", "status": 302, "timestamp": "2023-03-13T19:01:35.418604", "user": "akadmin", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0"}
authentik-server-1      | {"auth_via": "session", "event": "/if/flow/default-authenticator-webauthn-setup/?next=%2Fif%2Fuser%2F%23%2Fsettings%3B%7B%22page%22%3A%22page-mfa%22%7D", "host": "authentik.felix-ern.de", "level": "info", "logger": "authentik.asgi", "method": "GET", "pid": 21, "remote": "<CENSORED_IPV6>", "request_id": "6a904d738a364b009d432c7c162d6f49", "runtime": 29, "scheme": "https", "status": 200, "timestamp": "2023-03-13T19:01:35.493099", "user": "akadmin", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0"}
authentik-server-1      | {"event":"/static/dist/flow/FlowInterface.js?version=2023.3.0","host":"authentik.felix-ern.de","level":"info","logger":"authentik.router","method":"GET","remote":"<CENSORED_IPV6>","runtime":"0.362","scheme":"http","size":198,"status":200,"timestamp":"2023-03-13T19:01:35Z","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0"}
authentik-server-1      | {"event":"/static/dist/flow/locale-en-d17bb280.js","host":"authentik.felix-ern.de","level":"info","logger":"authentik.router","method":"GET","remote":"<CENSORED_IPV6>","runtime":"3.988","scheme":"http","size":125820,"status":200,"timestamp":"2023-03-13T19:01:35Z","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0"}
authentik-server-1      | {"event":"/static/dist/flow/FlowInterface-d86c1621.js","host":"authentik.felix-ern.de","level":"info","logger":"authentik.router","method":"GET","remote":"<CENSORED_IPV6>","runtime":"8.297","scheme":"http","size":0,"status":200,"timestamp":"2023-03-13T19:01:35Z","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0"}
authentik-server-1      | {"auth_via": "session", "event": "/api/v3/flows/executor/default-authenticator-webauthn-setup/?query=next%3D%252Fif%252Fuser%252F%2523%252Fsettings%253B%257B%2522page%2522%253A%2522page-mfa%2522%257D", "host": "authentik.felix-ern.de", "level": "info", "logger": "authentik.asgi", "method": "GET", "pid": 21, "remote": "<CENSORED_IPV6>", "request_id": "74233f540ede426cbb9e6754cc703067", "runtime": 30, "scheme": "https", "status": 200, "timestamp": "2023-03-13T19:01:35.832180", "user": "akadmin", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0"}
authentik-server-1      | {"auth_via": "unauthenticated", "event": "/if/flow/default-authenticator-webauthn-setup/?next=%2Fif%2Fuser%2F%23%2Fsettings%3B%7B%22page%22%3A%22page-mfa%22%7D", "host": "authentik.felix-ern.de", "level": "info", "logger": "authentik.asgi", "method": "GET", "pid": 21, "remote": "207.241.232.90", "request_id": "1762360dc1954173a64fd5929b37835d", "runtime": 14, "scheme": "https", "status": 200, "timestamp": "2023-03-13T19:01:36.823863", "user": "", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/605.1.15"}
authentik-postgresql-1  | 2023-03-13 19:01:52.885 UTC [342] ERROR:  value too long for type character varying(300)
authentik-postgresql-1  | 2023-03-13 19:01:52.885 UTC [342] STATEMENT:  INSERT INTO "authentik_stages_authenticator_webauthn_webauthndevice" ("confirmed", "user_id", "name", "credential_id", "public_key", "sign_count", "rp_id", "created_on", "last_t") VALUES (true, 1, 'WebAuthn Device', 'owBZARIiBSszqB5ZTCORkOSSDUf7um2lox0fvcMFPSTaLFv4KEy9KTpiQ9X1MvAij9XbRS72LuK2gcwC3pCvJ8sxehSuc_6p9SEIPOj8XI8Zht2qHr9sYKg0IYHow6OwofIJrr_cQOaa-_IM7MNTENZvJP9-HAboRHaZaWynXNP3lDMkHWwVR0kFTLiBo6S_45CDeh0dOCiNGyZagOslh_BuZd3sEZp594YsOONcba9MRR9aHpICbtzNiA0gsd98_KSX78-HRCLXsaJkVpKHy3qTxXohmT-v0m21MIG3oe8ioeq07eEYlLYGYeRPiXtW5pz8u1b2-Fd3WDXVMeNtFBpU6xgM0QJX0gJ1qmJEzwNPnV0is_xnAUyO74QwTzkhPeMBzrwCUAKcofZedlVWKp8p3-zZ3RA', 'pAEBAycgBiFYIE5FjFqOTjfuPBkUQpM3M0Zw_hjrrG-d6bgmxRJp7R4T', 35, 'authentik.felix-ern.de', '2023-03-13T19:01:52.884661+00:00'::timestamptz, '2023-03-13T19:01:52.884513+00:00'::timestamptz) RETURNING "authentik_stages_authenticator_webauthn_webauthndevice"."id"
authentik-server-1      | {"auth_via": "session", "event": "DataError('value too long for type character varying(300)\\n')", "flow_slug": "default-authenticator-webauthn-setup", "host": "authentik.felix-ern.de", "level": "warning", "logger": "authentik.flows.views.executor", "pid": 25, "request_id": "40402dade113443ba440bbd69697ce6b", "timestamp": "2023-03-13T19:01:52.909642"}
authentik-server-1      | {"action": "system_exception", "auth_via": "session", "client_ip": "<CENSORED_IPV6>", "context": {"geo": {"city": "D\u00fcsseldorf", "continent": "EU", "country": "DE", "lat": 51.2283, "long": 6.78}, "http_request": {"args": {"query": "next=%2Fif%2Fuser%2F%23%2Fsettings%3B%7B%22page%22%3A%22page-mfa%22%7D"}, "method": "POST", "path": "/api/v3/flows/executor/default-authenticator-webauthn-setup/"}, "message": "Traceback (most recent call last):\n  File \"/authentik/flows/views/executor.py\", line 340, in post\n    stage_response = self.current_stage_view.post(request, *args, **kwargs)\n                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/authentik/flows/stage.py\", line 137, in post\n    return self.challenge_valid(challenge)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/authentik/stages/authenticator_webauthn/stage.py\", line 128, in challenge_valid\n    WebAuthnDevice.objects.create(\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/manager.py\", line 85, in manager_method\n    return getattr(self.get_queryset(), name)(*args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 671, in create\n    obj.save(force_insert=True, using=self.db)\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/base.py\", line 812, in save\n    self.save_base(\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/base.py\", line 863, in save_base\n    updated = self._save_table(\n              ^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/base.py\", line 1006, in _save_table\n    results = self._do_insert(\n              ^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/base.py\", line 1047, in _do_insert\n    return manager._insert(\n           ^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/manager.py\", line 85, in manager_method\n    return getattr(self.get_queryset(), name)(*args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 1791, in _insert\n    return query.get_compiler(using=using).execute_sql(returning_fields)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py\", line 1660, in execute_sql\n    cursor.execute(sql, params)\n  File \"/usr/local/lib/python3.11/site-packages/sentry_sdk/integrations/django/__init__.py\", line 578, in execute\n    return real_execute(self, sql, params)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py\", line 67, in execute\n    return self._execute_with_wrappers(\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py\", line 80, in _execute_with_wrappers\n    return executor(sql, params, many, context)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py\", line 84, in _execute\n    with self.db.wrap_database_errors:\n  File \"/usr/local/lib/python3.11/site-packages/django/db/utils.py\", line 91, in __exit__\n    raise dj_exc_value.with_traceback(traceback) from exc_value\n  File \"/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py\", line 89, in _execute\n    return self.cursor.execute(sql, params)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.11/site-packages/django_prometheus/db/common.py\", line 71, in execute\n    return super().execute(*args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\ndjango.db.utils.DataError: value too long for type character varying(300)\n"}, "event": "Created Event", "host": "authentik.felix-ern.de", "level": "info", "logger": "authentik.events.models", "pid": 25, "request_id": "40402dade113443ba440bbd69697ce6b", "timestamp": "2023-03-13T19:01:52.914778", "user": {"email": "together+authentic-admin@felix-ern.de", "pk": 1, "username": "akadmin"}}
authentik-server-1      | {"auth_via": "session", "event": "Task published", "host": "authentik.felix-ern.de", "level": "info", "logger": "authentik.root.celery", "pid": 25, "request_id": "40402dade113443ba440bbd69697ce6b", "task_id": "bfc88385-69d9-475e-b7f1-4598ad44132a", "task_name": "authentik.events.tasks.event_notification_handler", "timestamp": "2023-03-13T19:01:52.936320"}
authentik-server-1      | {"auth_via": "session", "event": "/api/v3/flows/executor/default-authenticator-webauthn-setup/?query=next%3D%252Fif%252Fuser%252F%2523%252Fsettings%253B%257B%2522page%2522%253A%2522page-mfa%2522%257D", "host": "authentik.felix-ern.de", "level": "info", "logger": "authentik.asgi", "method": "POST", "pid": 25, "remote": "<CENSORED_IPV6>", "request_id": "40402dade113443ba440bbd69697ce6b", "runtime": 76, "scheme": "https", "status": 200, "timestamp": "2023-03-13T19:01:52.944305", "user": "akadmin", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0"}
```

**Version and Deployment (please complete the following information):**
 - authentik version: `2023.3.0` (but also happened on `2023.2.2`)
 - Deployment: docker-compose

**Additional context**
I've not yet had other problems with that security token, and a different model with "just" FIDO2 support registers flawlessly in Authentik.


Discussion:

Resolving patch:
diff --git a/authentik/stages/authenticator_webauthn/migrations/0008_alter_webauthndevice_credential_id.py b/authentik/stages/authenticator_webauthn/migrations/0008_alter_webauthndevice_credential_id.py
new file mode 100644
--- /dev/null
+++ b/authentik/stages/authenticator_webauthn/migrations/0008_alter_webauthndevice_credential_id.py
@@ -0,0 +1,20 @@
+# Generated by Django 4.1.7 on 2023-03-13 19:49
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        (
+            "authentik_stages_authenticator_webauthn",
+            "0007_rename_last_used_on_webauthndevice_last_t",
+        ),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="webauthndevice",
+            name="credential_id",
+            field=models.TextField(unique=True),
+        ),
+    ]
diff --git a/authentik/stages/authenticator_webauthn/models.py b/authentik/stages/authenticator_webauthn/models.py
--- a/authentik/stages/authenticator_webauthn/models.py
+++ b/authentik/stages/authenticator_webauthn/models.py
@@ -119,7 +119,7 @@ class WebAuthnDevice(SerializerModel, Device):
     user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
 
     name = models.TextField(max_length=200)
-    credential_id = models.CharField(max_length=300, unique=True)
+    credential_id = models.TextField(unique=True)
     public_key = models.TextField()
     sign_count = models.IntegerField(default=0)
     rp_id = models.CharField(max_length=253)


Test patch: