Skip to content

fix: accept a list of JWT audiences - #110

Merged
howbazaar merged 1 commit into
stacklet/integrationfrom
thumper/fix/jwt-audience-list
Sep 22, 2026
Merged

howbazaar merged 1 commit into
stacklet/integrationfrom
thumper/fix/jwt-audience-list

Conversation

@howbazaar

Copy link
Copy Markdown

what

REDASH_JWT_AUTH_AUDIENCE becomes comma-separated, parsed into a list the same way
REDASH_JWT_AUTH_ALGORITHMS on the next line already is. No other code changes: PyJWT
already accepts a list for audience= and admits a token matching any entry.

A value with no comma still yields a single-element list, and an empty one still yields
something falsy, which jwt_token_load_user_from_request continues to read as "do not
verify the audience". So existing deployments are unaffected.

why

A Cognito deployment mints tokens for more than one app client, and the aud claim
names the client a token was issued to, so a single configured value can only ever
admit one of them.

Stacklet's platform now fronts an MCP OAuth proxy that obtains its own Cognito tokens
on a user's behalf, through its own app client. Those tokens carry that client's id as
aud, while Redash is configured with the console's — so jwt.decode raises
InvalidAudienceError, jwt_token_load_user_from_request turns it into Unauthorized,
and the caller gets a 401 indistinguishable from a bad credential. Concretely, an MCP
client such as VS Code or Cursor authenticates fine and can reach the platform's
GraphQL API, but every AssetDB tool fails, because those reach Redash with the token in
the stacklet-auth cookie.

The platform side already solved this for its own API by accepting a list of audiences.
This is the same fix for Redash.

testing

Two tests added to TestJWTAuthentication: a token whose aud is the second of several
configured audiences is accepted, and one whose aud matches none is still rejected
(401, since verify_jwt_token raises rather than returning no user), so the list stays
a closed set.

I could not run the suite — it needs the Postgres/Redis services from this repo's own
test setup, which I had no way to stand up. The change was syntax-checked, the parsing
verified against empty / single / multi / whitespace / empty-segment inputs, and PyJWT's
list-audience behaviour confirmed directly. The new tests themselves are unexercised
and should be run before merge.

docs

None needed — the setting keeps its name and its single-value behaviour.

REDASH_JWT_AUTH_AUDIENCE is now comma-separated. A Cognito deployment mints
tokens for more than one app client, and the audience claim names the client a
token was issued to, so a single configured value can only ever admit one of
them. The console's own client was configured; a second client authenticating
the same user -- the platform's MCP OAuth proxy, which obtains its own tokens
on the user's behalf -- presents its own audience and was rejected with a 401
that was indistinguishable from a bad credential.

PyJWT already accepts a list and passes a token matching any entry, so this is
a settings change only. A value with no comma still yields a single-element
list, and an empty one still yields something falsy, which
jwt_token_load_user_from_request continues to read as "do not verify the
audience".
@howbazaar
howbazaar merged commit ba1b18c into stacklet/integration Sep 22, 2026
3 checks passed
@howbazaar
howbazaar deleted the thumper/fix/jwt-audience-list branch September 22, 2026 04:37
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