Skip to content

JWTConfig fields

Every field of authn.JWTConfig, what it defaults to, and what happens when it is wrong. All fields are optional in the Go sense — the zero value compiles — but NewJWTVerifier refuses to build without an issuer and a JWKS URL.

Field Type Default Required
Issuer string none Yes, unless supplied by WithOIDCDiscovery
Audiences []string none — check disabled No
JWKSURL string none Yes, unless supplied by WithOIDCDiscovery
Leeway time.Duration 60s No
RefreshInterval time.Duration 15m No
AllowedAlgorithms []string RS256 RS384 RS512 ES256 ES384 ES512 No
HTTPClient *http.Client &http.Client{Timeout: 10 * time.Second} No

Issuer

The value the token's iss claim must equal. Matching is exact.

  • Missing: construction fails with authn: JWT verifier requires an Issuer.
  • Mismatched at verification: the token is rejected. iss is also required on the token — a token with no iss claim at all is rejected the same way.
  • Overwritten: WithOIDCDiscovery replaces whatever you set here with the discovery document's issuer, silently. See Discovery overwrites a configured Issuer.

Audiences

The acceptable aud values, matched any-of: the token is accepted if any of its audiences appears in this list.

  • Empty (the default): the audience check is skipped entirely. Any token from the right issuer is accepted regardless of who it was minted for, which means a token issued for a different service in the same realm will authenticate against yours. Set it.
  • Set, and the token has no aud claim: rejected with audience not accepted.
  • Token aud shapes handled: a JSON string, a JSON array of strings, or a Go []string. Non-string members of an array are ignored rather than causing an error. Any other shape — a number, an object — yields no audiences and therefore a rejection when Audiences is set.

The audience check is authn's own, run after the token's signature and standard claims have been validated.

JWKSURL

The JSON Web Key Set endpoint the signing keys are fetched from.

  • Missing: construction fails with authn: JWT verifier requires a JWKS URL (set JWKSURL or WithOIDCDiscovery).
  • Not HTTPS: construction fails with authn: JWKS URL must be HTTPS, got "http". There is no opt-out, and no allowance for localhost or a plaintext test server.
  • Unparseable: construction fails with authn: parse JWKS URL: ….
  • Reachable but wrong: construction fails with authn: initial JWKS fetch: authn: JWKS endpoint returned 404 (or whatever status came back).
  • Overwritten: WithOIDCDiscovery replaces whatever you set here with the document's jwks_uri.

A document that parses but contains no usable key material does not fail construction — see What the initial fetch does and does not catch.

Leeway

Clock-skew tolerance applied when checking time-based claims.

  • Default: 60 seconds. Any value <= 0 is replaced by the default, so you cannot configure zero leeway.
  • Applies to: exp and nbf. A token that expired 30 seconds ago is accepted with the default leeway; one that expired 5 minutes ago is not. A token whose nbf is 30 seconds in the future is accepted; 5 minutes in the future is not.
  • Does not apply to iat. The issued-at claim is not validated at all — it is neither required nor checked for being in the future.

RefreshInterval

How long a fetched JWKS is considered current. It is a staleness threshold, not a rate limit.

  • Default: 15 minutes. Any value <= 0 is replaced by the default.
  • Effect: while the cached key set is younger than RefreshInterval, no network fetch happens — including when a token arrives with a kid the cache has never seen. A signing key that appears mid-interval is therefore not picked up until the interval elapses, and tokens signed with it are rejected until then. This is the single most surprising behaviour in the package; Why a rotated signing key can be rejected for up to fifteen minutes explains the mechanism and how to choose a value.
  • Lower bound in practice: once the cache is stale, a failed refresh is not retried for 30 seconds. That floor is a package constant and is not configurable — see Defaults and hard limits.

AllowedAlgorithms

The alg header values a token may carry.

  • Default: RS256, RS384, RS512, ES256, ES384, ES512.
  • none is refused at construction, in any letter case: authn: algorithm "none" is never allowed.
  • Any value beginning HS is refused at construction, in any letter case: authn: HMAC algorithm "HS256" is not allowed with a JWKS (alg-confusion defence). There is no way to enable HMAC verification — see What authn does not do.
  • PS256/PS384/PS512 are accepted if you list them explicitly. They are not in the default set, so RSA-PSS tokens are rejected until you add them.
  • Matching is case-sensitive at verification time. The construction-time check upper-cases before rejecting, but the accept list is compared against the token's alg header verbatim. Listing "rs256" builds fine and then rejects every RS256 token with token signature is invalid: signing method RS256 is invalid. Use the upper-case spelling.

Setting this to a single algorithm is a reasonable hardening step when you know what your issuer signs with. Setting it to a value the issuer does not use locks you out entirely.

HTTPClient

The client used for both the OIDC discovery fetch and every JWKS fetch.

  • Default: a fresh &http.Client{Timeout: 10 * time.Second}.
  • A client you supply is used as-is, including its Transport, so this is where a proxy, a custom root pool for an internal issuer, or connection reuse goes.
  • Your Timeout is not the only bound. Each fetch also runs under a 10-second context deadline that is a package constant, so a client with a longer timeout still gives up at 10 seconds. A shorter client timeout wins.
  • It is not used for anything else. authn makes no other outbound calls.