Hello,
I'm hoping to get some insight or support on an issue I've been stuck on for over three days involving OIDC integration with OpenZiti.
Network:
- OpenZiti Controller: Installed directly (non-Docker) on a VPS (public)
- Ziti Routers: Several — a mix of LAN and cloud (working correctly)
- OIDC Provider: Authentik (hosted on the LAN side, reverse proxied)
The core network is functioning flawlessly — tunnels, identities, routers, services, all configured and working as expected.
I've now looking to integrated Authentik for SSO via OIDC using PKCE flow so i can test out Browzer, and everything appears to be functioning until the final POST to the controller for authentication. At that point, the controller responds with:
API request[/authenticate] failed code[INVALID_AUTH] message[The authentication request failed]
I am getting a successful flow, and token generated according to the tunnel logs but then when ever the authentication attempts to post to the controller it fails,
From the client tunnel logs:
- Token request completes (200 OK)
- ID token and access token are issued
- Tokens contain the correct
iss
,aud
,email
,sub
,azp
, etc. - Ziti correctly receives and decodes the token
Yet, authentication fails at the controller step. Here's the log snippet (with sensitive fields redacted):
[2025-03-23T22:56:45.925Z] INFO ziti-sdk:oidc.c:411 request_token() requesting token path[https://<AUTHENTIK_HOST>/application/o/token/] auth[<REDACTED_AUTH_CODE>]
[2025-03-23T22:56:46.306Z] DEBUG ziti-sdk:oidc.c:395 token_cb() 200 OK
[2025-03-23T22:56:46.306Z] DEBUG ziti-sdk:oidc.c:902 oidc_client_set_tokens() using access_token={
"iss": "https://<AUTHENTIK_HOST>/application/o/openziti-api/",
"sub": "<REDACTED_SUBJECT_ID>",
"aud": "authentik_openziti",
"exp": 1742770910,
"iat": 1742770610,
"auth_time": 1742759485,
"acr": "goauthentik.io/providers/oauth2/default",
"email": "user@example.com",
"email_verified": true,
"name": "John Doe",
"given_name": "John",
"preferred_username": "john.doe",
"nickname": "john.doe",
"groups": ["authentik Admins", "web backend"],
"azp": "authentik_openziti",
"uid": "<REDACTED_UID>"
}
[2025-03-23T22:56:46.306Z] DEBUG ziti-sdk:external_auth.c:90 ext_token_cb() received access token: eyJhbGciOiJSUzI1NiIs...<REDACTED>
[2025-03-23T22:56:46.306Z] DEBUG ziti-sdk:oidc.c:913 oidc_client_set_tokens() scheduling token refresh in 300 seconds
[2025-03-23T22:56:46.444Z] DEBUG ziti-sdk:ziti_ctrl.c:499 ctrl_body_cb() ctrl[https://<ZITI_CONTROLLER_HOST>:1280] completed POST[/authenticate] in 0.135 s
[2025-03-23T22:56:46.444Z] ERROR ziti-sdk:ziti_ctrl.c:521 ctrl_body_cb() ctrl[https://<ZITI_CONTROLLER_HOST>:1280] API request[/authenticate] failed code[INVALID_AUTH] message[The authentication request failed]
[2025-03-23T22:56:46.444Z] ERROR ziti-sdk:ziti_ctrl.c:388 ctrl_login_cb() ctrl[https://<ZITI_CONTROLLER_HOST>:1280] INVALID_AUTH(The authentication request failed)
[2025-03-23T22:56:46.444Z] DEBUG ziti-sdk:ziti_ctrl.c:379 ziti_ctrl_clear_api_session() ctrl[https://<ZITI_CONTROLLER_HOST>:1280] clearing api session token for ziti_controller
[2025-03-23T22:56:46.444Z] WARN ziti-sdk:legacy_auth.c:183 login_cb() failed to login to ctrl[https://<ZITI_CONTROLLER_HOST>:1280/] INVALID_AUTH[-14] The authentication request failed
[2025-03-23T22:56:46.444Z] DEBUG ziti-sdk:ziti.c:266 ziti_set_impossible_to_authenticate() ztx[0] setting api_session_state[0] to 4
[2025-03-23T22:56:46.444Z] DEBUG ziti-sdk:ziti_ctrl.c:379 ziti_ctrl_clear_api_session() ctrl[https://<ZITI_CONTROLLER_HOST>:1280] clearing api session token for ziti_controller
[2025-03-23T22:56:46.444Z] WARN tunnel-cbs:ziti_tunnel_ctrl.c:1004 on_ziti_event() ziti_ctx controller connections failed: failed to authenticate
[2025-03-23T22:56:46.444Z] INFO ziti-edge-tunnel:ziti-edge-tunnel.c:456 on_event() ztx[C:\...netfoundry\<REDACTED_CONFIG>.json] context event : status is failed to authenticate
[2025-03-23T22:56:46.444Z] ERROR ziti-edge-tunnel:ziti-edge-tunnel.c:510 on_event() ztx[C:\...netfoundry\<REDACTED_CONFIG>.json] failed to connect to controller due to failed to authenticate
What I’ve Confirmed or Tried
iss
,aud
, andjwks_uri
are exact matches (copied from.well-known/openid-configuration
)- JWT signer and Auth Policy are correctly registered and show in the controller (
ziti edge list
) - Tried using
email
andsub
as theclaimsProperty
, mapped to anexternalId
on the identity - Verified the identity exists and is assigned the correct Auth Policy
- Tried with:
- existing identity (matching external ID)
- new identity creation via OIDC
- Token decodes successfully with all expected fields (via JWT.io)
- Tried with public and confidential client modes
- Controller logging is enabled (
debug
), but nothing relevant is logged for this failure - Controllers domain is verified via third-party cert, and is not using the same as the advertised address.
The fact that Ziti SDK decodes the token, logs it, i get redirected to a successful callback and proceeds to call /authenticate
, but still gets a INVALID_AUTH
with no additional context from the controller, makes this difficult to debug.
I've tried re-creating everything, i've checked outside of Zac, directly on the controller to ensure the auth policies and the JWT provider have been registered and they have done. Decoded the tokens to ensure the payloads contain the rellevant data.
Unfortunatly out of ideas on where else to troubleshoot this one.
- Are there any additional controller log levels or flags to enable deeper OIDC-specific debug output?
- Is there any known edge case where Ziti decodes a token but fails to authenticate even when
claimsProperty
matchesexternalId
? - Could this be a scope or claim mapping issue even though
email
andsub
are included in the JWT and policy? - Can I manually validate the token or debug the controller validation logic?
- Are there any differences in controller behavior depending on whether identities are created automatically vs pre-created?
- Does any part of the flow need to publically access the JWT endpoint?
I’ve reviewed the updated docs here:
https://ziti-doc-git-issue-1022using-idps-openziti.vercel.app/docs/guides/external-auth/identity-providers/authentik
And implemented everything step-by-step.
Any help would be hugely appreciated!
Thanks,
C