Re: OpenTalk Controller returns 401 on /v1/me — issuer trailing slash mismatch with Authelia

Maximilian Meßmer m.messmer at opentalk.eu
Thu May 28 09:27:40 CEST 2026


Hello,

First of all, thank you for your thorough report on your findings.

There were some discussions about alternatives to Keycloak as an OIDC 
provider in OpenTalk in our matrix channels, where some of the members 
shared their experience with trying to get Authelia to run. Sadly its 
currently not possible to use anything other than Keycloak as your OIDC 
provider for OpenTalk. The main workaround would be to have Keycloak 
delegate the authentication to Authelia, but that would propably not 
work for you as you are looking for a "leaner" solution.

Regarding some of your questions:

1. Currently there is no such configuration option.

2. We validate the JWT token locally only if the IdP doesn't communicate 
an introspection enpoint in the `.well-known...`.

4. Internally we are currently doing tests with kanidm(not working yet 
though).

5. You can increase the log level in the configuration of the 
controller. 
https://docs.opentalk.eu/25.4/admin/controller/core/logging/log_output/

Best regards,
Max Meßmer

On 5/26/26 1:20 AM, holger.banzhaf--- via Opentalk-general wrote:
> Hello,
>
> I am trying to run the OpenTalk Controller with Authelia as an 
> external OIDC provider. Login and token issuance work, but all 
> authenticated API calls return 401. I have spent considerable time 
> debugging this and would appreciate guidance from anyone who has 
> successfully integrated Authelia with OpenTalk.
>
>
> ## Setup
>
> - OpenTalk Controller: registry.opencode.de/opentalk/controller:latest 
> (rootless Podman / systemd Quadlet)
> - OpenTalk Frontend: rootless Podman / systemd Quadlet
> - LiveKit: native binary, systemd service (not containerized)
> - coturn: native apt package, systemd service (not containerized)
> - Authelia: v4.39.19 (rootless Podman / systemd Quadlet)
> - Reverse Proxy: Traefik v3
> - OpenTalk frontend: talk.example.org
> - Authelia: auth.example.org
>
>
> ## Symptom
>
> After a successful OIDC login, the frontend briefly shows the 
> dashboard, then immediately redirects back to the login page. A direct 
> API call with a valid access token returns:
>
> ```
> HTTP/2 401
> {"code":"unauthorized","message":"Authentication failed"}
> ```
>
> The controller produces no log output for these rejected requests, 
> which makes diagnosis quite difficult.
>
>
> ## Problem 1: Issuer URI trailing slash mismatch
>
> This is our primary suspected root cause.
>
> Authelia always issues tokens with the issuer URL without a trailing 
> slash:
>
> ```
> iss: "https://auth.example.org"
> ```
>
> From what we can tell, the OpenTalk Controller — apparently due to the 
> behaviour of the openidconnect-rs library (RFC 8414) — normalizes the 
> configured `authority` value by always appending a trailing slash 
> internally. It then validates the `issuer` field in the OIDC discovery 
> document against this normalized value.
>
> In practice, regardless of whether `authority` in controller.toml is 
> set with or without a trailing slash, the controller seems to always 
> expect the discovery document to contain:
>
> ```
> "issuer": "https://auth.example.org/"
> ```
>
> but Authelia returns:
>
> ```
> "issuer": "https://auth.example.org"
> ```
>
> This causes the controller to fail at startup with:
>
> ```
> Validation error: unexpected issuer URI `https://auth.example.org`
> (expected `https://auth.example.org/`)
> ```
>
> We worked around the startup failure by rewriting the discovery 
> document `issuer` field via a Traefik middleware, so that the 
> controller sees the trailing slash and starts successfully.
>
> However, the problem appears to recur at runtime: when using JWT 
> access tokens (`access_token_signed_response_alg: RS256`), the signed 
> JWT still carries `iss: "https://auth.example.org"` (without trailing 
> slash), since a signed JWT cannot be rewritten in transit. We believe 
> the controller then rejects the token during local JWT issuer 
> validation, producing the 401 — though we are not fully certain about 
> the internal validation logic.
>
> When using opaque access tokens (without RS256), the controller falls 
> back to introspection — but this leads to Problem 2 below.
>
>
> ## Problem 2: Introspection client authentication method
>
> When the opentalk client is configured without 
> `access_token_signed_response_alg: RS256`, Authelia issues opaque 
> tokens (`authelia_at_...`). The controller must then validate these 
> via the introspection endpoint, authenticating itself as the 
> `opentalk-controller` client.
>
> We observed two distinct failure modes here and tested them directly.
>
> **a) client_secret_post**
>
> Credentials sent in the HTTP request body:
>
> ```bash
> curl -s -X POST \
>   -d 'client_id=opentalk-controller&client_secret=SECRET&token=TOKEN' \
>   https://auth.example.org/api/oidc/introspection
>
> # Result: HTTP 401 — request_unauthorized
> ```
>
> Authelia rejects this when the client is registered with 
> `token_endpoint_auth_method: client_secret_basic`.
>
> **b) client_secret_basic**
>
> Credentials sent as HTTP Basic Auth:
>
> ```bash
> curl -s -X POST \
>   -u 'opentalk-controller:SECRET' \
>   -d 'token=TOKEN' \
>   https://auth.example.org/api/oidc/introspection
>
> # Result: HTTP 200 — {"active":true,...}
> ```
>
> This works correctly. We therefore believe the OpenTalk Controller 
> uses `client_secret_basic` for introspection (credentials in the 
> Authorization header, not in the POST body). We confirmed this by 
> decoding the Authorization header captured in Traefik access logs:
>
> ```
> Authorization: Basic base64(opentalk-controller:SECRET)
> ```
>
> With a dummy token we correctly receive `{"active": false}`, and with 
> a real token `{"active": true}`. So introspection itself appears to 
> work when Authelia is configured with `token_endpoint_auth_method: 
> client_secret_basic`.
>
> Despite this, the controller still returns 401. This leads us to 
> suspect it performs additional local validation beyond introspection — 
> possibly a JWT issuer check — which fails due to the trailing slash 
> mismatch described in Problem 1. But again, we are not certain about 
> the internals here.
>
> ## Problem 3: Access Token with empty `aud` claim
>
> Without explicit `audience` configuration, Authelia issues access 
> tokens with an empty `aud` claim:
>
> ```json
> "aud": []
>
> We worked around this by adding audience: [opentalk-controller] to the 
> Authelia client configuration, so the token now contains:
>
> "aud": ["opentalk-controller"]
>
> We are not certain whether OpenTalk requires a specific value in aud, 
> or whether an empty aud causes the token to be rejected outright. Any 
> clarification on what the controller expects here would be helpful.
>
>
>
>
> ## Current Authelia client configuration
>
> ```yaml
> - client_id: opentalk
>   public: true
>   authorization_policy: one_factor
>   redirect_uris:
>     - https://talk.example.org/auth/callback
>   scopes: [openid, profile, email]
>   token_endpoint_auth_method: none
>   id_token_signed_response_alg: RS256
>   access_token_signed_response_alg: RS256
>   audience:
>     - opentalk-controller
>   claims_policy: opentalk_claims  # includes given_name, family_name, 
> email, preferred_username
>   consent_mode: implicit
>
> - client_id: opentalk-controller
>   public: false
>   client_secret: "..."
>   token_endpoint_auth_method: client_secret_basic
>   scopes: [openid, profile, email]
> ```
>
>
> ## Current controller.toml [oidc] section
>
> ```toml
> [oidc]
> authority = "https://auth.example.org"
>
> [oidc.frontend]
> authority = "https://auth.example.org"
> client_id = "opentalk"
>
> [oidc.controller]
> client_id = "opentalk-controller"
> client_secret = "..."
> ```
>
>
> ## Questions
>
> 1. Is the issuer URI trailing slash mismatch a known incompatibility 
> between OpenTalk and Authelia? Is there any controller-side 
> configuration to relax or override the issuer validation?
>
> 2. At runtime, does the controller validate JWT access tokens locally 
> (signature + issuer check) in addition to — or instead of — calling 
> the introspection endpoint? If so, is there a way to configure it to 
> rely exclusively on introspection?
>
> 3. Is `audience: [opentalk-controller]` the correct way to populate 
> the `aud` claim in the access token when using Authelia? Without this 
> setting, Authelia issues tokens with `"aud": []`, which we suspect may 
> also cause issues.
>
> 4. Has someone ever tested Authelia  as an OIDC provider for OpenTalk? 
> If not, are there known working alternatives besides Keycloak? I ask 
> because I need a very lean setup.
>
> 5. Are there controller debug flags or log levels that would produce 
> more detailed output on 401 rejections? Currently the controller logs 
> nothing for these requests, which makes it very hard to understand 
> what is actually being validated.
>
> Thank you for any ideas and guidance.
> Cheers
> Holger


More information about the Opentalk-general mailing list