Notes on ZITADEL, Proxmox and Audience Validation

While setting up OpenID Connect authentication between ZITADEL and Proxmox VE, I ran into an issue that took longer to understand than I expected.

Authentication appeared to succeed on the ZITADEL side, but Proxmox refused to accept the returned token and logged the following error:

openid authentication failure; rhost=::ffff:192.168.178.81
msg=Failed to verify ID token:
Invalid audiences: `377572587972067335` is not a trusted audience

At first glance this was confusing. The token had been issued specifically for the Proxmox application, so why was audience validation failing?

Looking at the ID token revealed the following audience claim:

{
  "aud": [
    "377576883644006407",
    "377572587972067335"
  ]
}

The first value was my Proxmox OAuth client. The second was the ZITADEL project ID.

My initial assumption was that Proxmox should simply check whether its client ID appeared somewhere in the list and accept the token. After all, the token was clearly intended for the client.

After reading the OpenID Connect specification more carefully, I realized the situation is a bit more nuanced. The relevant section is even quoted directly in the Proxmox source code:

// 3. The Client MUST validate that the aud (audience) Claim contains its client_id value
// registered at the Issuer identified by the iss (issuer) Claim as an audience. The aud
// (audience) Claim MAY contain an array with more than one element. The ID Token MUST be
// rejected if the ID Token does not list the Client as a valid audience, or if it
// contains additional audiences not trusted by the Client.

The part I had overlooked was the final sentence. Multiple audiences are perfectly valid, but the client is expected to trust all audiences present in the token.

In hindsight, Proxmox was behaving exactly as specified. The token contained an additional audience that Proxmox did not know about, so it rejected the token.

What surprised me more was ZITADEL’s behavior. By default, ZITADEL includes both the client ID and the project ID in the audience claim. From ZITADEL’s perspective this makes sense and enables additional authorization scenarios, but it can create interoperability issues with clients that perform strict audience validation.

Naturally, my next question was whether this behavior could be disabled. I expected to find a setting somewhere in the console or an option on the application. After some searching, I found an open feature request discussing exactly this scenario, including Proxmox as an example. As far as I can tell, the additional project audience is currently not configurable. As you can see there are other github projects referencing this issues like rustdesk/rustdesk-server-pro, rustfs/rustfs and some adding an audience check to work with ZITADEL.

The practical solution was therefore not to change ZITADEL but to configure Proxmox to trust the additional audience:

openid: zitadel
    client-id 377576883644006407
    audiences 377572587972067335

After adding the project ID as a trusted audience, authentication succeeded.

The whole experience was a useful reminder that standards compliance and interoperability are not always the same thing. Both ZITADEL and Proxmox were doing reasonable things. The problem was simply that they made different assumptions about how audience validation should be handled.

Most of the time OAuth and OpenID Connect “just work”. Every now and then, however, you run into one of these small details hidden deep in the specification and spend an evening learning something new.

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Spelling error report

The following text will be sent to our editors: