NAME

Punk::OAuth2::JWKS - a cached JWKS key set

SYNOPSIS

my $jwks = Punk::OAuth2::JWKS->new(
	url => 'https://idp.example.com/oauth/jwks.json');

my $key = $jwks->key_for($c, $kid);   # Crypt::JWS::Key or undef

DESCRIPTION

Fetches a JWKS document, imports each entry through "from_jwk" in Crypt::JWS::Key, and caches kid to key per worker, implemented in XS. An unknown kid triggers exactly one (rate-limited) refetch to cover key rotation; a kid still unknown afterwards is negative-cached so attacker-chosen kids cannot become a fetch stream. The URL passes the SSRF guard at construction.

You rarely use this directly - "jwt" in Punk::OAuth2::Checker and the client's OIDC verification build and drive it for you.

METHODS

new

my $jwks = Punk::OAuth2::JWKS->new(
	url         => 'https://idp.example.com/oauth/jwks.json',
	ttl         => 6 * 3600,   # cache lifetime (default 6h)
	ua          => $agent,     # a Fetch-like agent, optional
	allow_local => 0,          # relax the SSRF guard for loopback
);

Croaks if the URL fails the SSRF guard (https, resolves to a public address) unless allow_local is set.

key_for

my $key = $jwks->key_for($c, $kid);

Returns the Crypt::JWS::Key for $kid, fetching (via $c->ua or the configured agent) and caching as needed, or undef. $c may be undef when no request context is available.

AUTHOR

LNATION, <email at lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)