Skip to content

Conversation

gigi206
Copy link
Contributor

@gigi206 gigi206 commented Oct 14, 2025

Problem:
When using certain OpenID Connect (OIDC) providers (e.g., LemonLDAP) where the sub claim (subject identifier) is not formatted as a UUID, users encountered an "Invalid LiveKit token" error when attempting to activate features requiring LiveKit token authentication (e.g., real-time subtitles).

The error message indicated that the value provided was "not a valid UUID", specifically during the UserModel.objects.get(id=user_id) lookup in the LiveKitTokenAuthentication process.

Root Cause:
The LiveKitTokenAuthentication class in src/backend/core/authentication/livekit.py attempts to retrieve a Django User object using UserModel.objects.get(id=user_id), where user_id is derived from the identity field of the LiveKit token. The identity for authenticated users was previously set to str(user.sub) in the generate_token utility function.

While LiveKit itself expects an identity string, the Django User model's id field is a UUID. If the OIDC sub claim (which populates user.sub) is not a UUID, a mismatch occurs when the application tries to fetch the user by their id using this non-UUID sub value. This leads to a FieldError or ValidationError during the database lookup, causing the LiveKit token validation to fail.

Solution:
To ensure robust compatibility with all OIDC providers, the generate_token function in src/backend/core/utils.py has been modified. Instead of using str(user.sub) as the identity for the LiveKit token, it now consistently uses str(user.id).

The user.id field is the internal Django User ID, which is guaranteed to be a valid UUID. This change ensures that the LiveKit token's identity always matches the format expected by the UserModel.objects.get(id=...) lookup, regardless of the format of the OIDC sub claim.

Impact:
This fix resolves the "Invalid LiveKit token" error for users authenticated via OIDC providers that do not provide UUIDs in their sub claims. It improves the application's compatibility and reliability across diverse authentication environments.

@gigi206 gigi206 force-pushed the fix_django_id_livekit branch 3 times, most recently from f99dcf7 to 3015144 Compare October 14, 2025 16:46
@lebaudantoine
Copy link
Collaborator

lebaudantoine commented Oct 16, 2025

Hi,

Thanks for your contribution, good catch!
This feature is not yet documented and released, we're not using it yet.

I agree with your point regarding the bug/issue; however, I would recommend updating the broken section within the LiveKit authentication class itself rather than modifying this part of the code, which is tied to much more logic. I would also prefer not to rely heavily on the database’s application ID and would rather continue using sub as the identifier.

"To ensure robust compatibility with all OIDC providers, the generate_token function in src/backend/core/utils.py has been modified. Instead of using str(user.sub) as the identity for the LiveKit token, it now consistently uses str(user.id)."

I’m not sure why this change would be necessary. By definition, sub should be a valid, unique ASCII string up to 255 characters long [RFC 7519] and can reliably identify a user. Do you have a specific OIDC provider in mind where this could be an issue?

Thanks,

Fixes "Invalid LiveKit token" errors caused by field mismatch between
token generation and authentication lookup.

Previously:
- generate_token() used user.sub as token identity
- LiveKitTokenAuthentication tried to retrieve user via user.id field
- This failed when sub was not a UUID (e.g., from LemonLDAP OIDC provider)

Now:
- generate_token() continues using user.sub (canonical OIDC identifier)
- LiveKitTokenAuthentication correctly looks up by sub field
- Both sides now consistently use the same field

This ensures compatibility with all RFC 7519-compliant OIDC providers,
regardless of their sub claim format.
@gigi206 gigi206 force-pushed the fix_django_id_livekit branch from 3015144 to 28e9a8c Compare October 17, 2025 11:43
Copy link

@gigi206
Copy link
Contributor Author

gigi206 commented Oct 17, 2025

Thanks for your review and feedback! You're right - fixing the LiveKitTokenAuthentication class is the better architectural approach.

The actual bug: the issue isn't that sub is invalid per RFC 7519. The bug is a field mismatch between token generation and authentication:

  • generate_token() in utils.py:102 was using str(user.sub) as the token identity
  • LiveKitTokenAuthentication.authenticate() in livekit.py:33 tried to retrieve the user with UserModel.objects.get(id=user_id)

This means we were looking up by the id field (Django's UUID) using a value from the sub field (which can be any RFC 7519-compliant string).

Specific OIDC provider: we encountered this issue with LemonLDAP::NG, where the sub claim is not formatted as a UUID. When the authentication class tries UserModel.objects.get(id=non_uuid_sub), Django raises a validation error:

Invalid LiveKit token: badly formed hexadecimal UUID string

Updated fix: I've updated the PR to implement your suggested approach:

  • Keep using user.sub as the identity in token generation (it's the canonical OIDC identifier)
  • Fix LiveKitTokenAuthentication to look up users by the sub field instead of id

This ensures both sides consistently use the same field and maintains compatibility with all RFC 7519-compliant OIDC providers, regardless of their sub claim format.

The commit has been updated accordingly.

Thanks for the guidance!

@lebaudantoine
Copy link
Collaborator

Perfect that exactly what I had in mind!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants