NAME

Catalyst::Plugin::OAuth2::ResourceServer::Server - bearer-JWT verification engine for the ResourceServer plugin

DESCRIPTION

Pure-logic engine (a Moo object) that holds the verification parameters and performs bearer-JWT validation independently of Catalyst. Attributes: signing_key (required), resource (required: scalar or arrayref), issuer (required), jwt_alg (default HS256), leeway (default 0).

The engine is constructed per request by the Catalyst seam (Catalyst::Plugin::OAuth2::ResourceServer) from the app config, so there is no persistent state between requests.

METHODS

verify_token( $jwt )

my $claims = $engine->verify_token($bearer_token_string);

Verifies a bearer JWT string. Steps performed:

  • Signature verification using signing_key and the HS-alg allowlist (HS256, HS384, HS512 only: alg=none and asymmetric algorithms are always rejected).

  • Expiry (exp) check with optional leeway seconds of clock-skew tolerance. exp is required: a token carrying no expiry is rejected.

  • Not-before (nbf) and issued-at (iat) checks, also honouring leeway. Both claims are optional (RFC 7519 4.1.5 and 4.1.6), so they are validated only when present: a token whose nbf is in the future, or whose iat is in the future, is rejected, but a token omitting either verifies normally. This matches what Catalyst::Plugin::OAuth2::AuthorizationServer mints, which stamps iss, aud, iat and exp but no nbf.

  • Issuer (iss) match against the configured issuer. The match is an exact string comparison, not a substring or prefix match: an iss of https://as.exampleEVIL does not satisfy a configured issuer of https://as.example.

  • Payload type guard: the decoded payload must be a claims hashref.

  • Audience (aud) membership check: at least one aud value must match one of the configured resource identifiers.

Returns the claims hashref on success. Throws a 401 Catalyst::Plugin::OAuth2::ResourceServer::Error with error = 'invalid_token' on any failure; the error description is never forwarded to clients.