Skip to content

Add checkIssuerClaim to enforce the JWT iss claim on the issuerUrl path #656

Description

@Aman-Cool

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:

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 :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions