Kuadrant / Kuadrant/authorino

Add `checkIssuerClaim` to enforce the JWT `iss` claim on the `issuerUrl` path

Open
#656 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
269
Forks
52
Avg merge
5d 17h
Merged PRs (30d)
13

Description

While reading through the JWT authentication code, I noticed that when you configure `issuerUrl`, Authorino verifies the token's signature and expiry.., but it never checks that the token's `iss` claim actually matches the issuer it discovered. I asked about it, and it was confirmed this is intentional: issuer-checking is opt-in today, done via an authorization rule (CEL / pattern-matching / OPA), and kept consistent with the `jwksUrl` path on purpose.

That makes sense. The one place it can bite is when two different issuers happen to **share signing keys**; e.g. a multi-tenant IdP, or Festival Wristbands issued by two AuthConfigs pointing at the same signing-key Secret. In that case a token minted by issuer A can satisfy a config trusting issuer B, because it's only the signature being checked and the keys match. And it's quiet... the token lands as a valid identity, and nothing in the logs hints at it. Someone who hasn't added the authorization rule wouldn't know.

So this isn't a bug report: it's the RFE that came out of that discussion: give people a way to enforce the issuer directly, without needing a separate authorization rule.

**The proposal:**

```yaml
authentication:
my-oidc:
jwt:
issuerUrl: https://issuer.example.com
checkIssuerClaim: true # new field, defaults to false
```

- `checkIssuerClaim` defaults to `false`, so nothing changes for anyone on upgrade.
- When `true`, Authorino rejects any token whose `iss` doesn't match `issuerUrl`, right at the authentication phase. (The discovered OIDC provider already knows the expected issuer, so it's basically letting the library do the check it was going to do anyway.)
- No effect on `jwksUrl`, which has no expected issuer to compare against.
- To make the opt-in nature discoverable, an INFO log at reconciliation when an `issuerUrl` config is used without `checkIssuerClaim`, plus a note in the docs.

I've got this working locally already (field + verifier change + docs + the reconciliation log), with tests covering both settings and a passing `make e2e` against real Keycloak confirming normal tokens still authenticate. Happy to open the PR right after this.

One thing I left out on purpose: there was also an idea for `checkClientID` / `clientID` for audience validation. That felt like a separate enough concern that I kept it out of this to keep the change focused.., glad to do it as a follow-up if that's wanted.

Thanks for @guicassolato for his help on this :)

Contributor guide

Open the contributing guide

Research direction

Start with the JWT authentication configuration and verifier, then review the existing documentation and reconciliation logging around issuerUrl. Done means adding the opt-in field with a false default, enforcing the issuer only when enabled, leaving jwksUrl unchanged, covering both settings in tests, and running make e2e against Keycloak.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, kubernetes
Domain
authentication, security
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.