Catalyst-Plugin-OAuth2-ResourceServer
view release on metacpan or search on metacpan
lib/Catalyst/Plugin/OAuth2/ResourceServer.pm view on Meta::CPAN
package Catalyst::Plugin::OAuth2::ResourceServer;
use v5.36;
use Scalar::Util qw/blessed/;
use JSON::MaybeXS ();
use Try::Tiny;
use URI ();
use Catalyst::Plugin::OAuth2::ResourceServer::Server;
use Catalyst::Plugin::OAuth2::ResourceServer::Error;
our $VERSION = '0.003';
my $CONFIG_KEY = 'Catalyst::Plugin::OAuth2::ResourceServer';
my $SLOT = 'Catalyst::Plugin::OAuth2::ResourceServer/ctx';
my $JSON = JSON::MaybeXS->new( utf8 => 1, canonical => 1 );
sub _oauth_rs_config ( $c ) { return $c->config->{$CONFIG_KEY} // {} }
# RFC 7230 quoted-string: backslash-escape `\` and `"` so a value carrying
# either cannot terminate the quoted-string or forge extra auth-params.
# A plain function, not a method.
sub _oauth_rs_quote_hval ( $value ) {
my $v = $value // '';
$v =~ s/([\\"])/\\$1/g;
return $v;
}
# RFC 9728 3.1: derive the protected-resource metadata URL from the resource
# identifier by inserting the well-known segment after the authority, before
# the resource's path. This is only defined for an http(s) resource id: for a
# URN or any other non-hierarchical scheme there is no authority to insert
# after, so return undef and let the caller omit the parameter rather than
# emit a malformed one. A plain function, not a method.
sub _oauth_rs_metadata_url ( $base ) {
return undef unless defined $base && length $base;
my $u = URI->new($base);
return undef unless $u->can('scheme') && defined $u->scheme;
return undef unless $u->scheme =~ /\A https? \z/xi;
return undef unless $u->can('authority') && $u->can('path');
return undef unless defined $u->authority && length $u->authority;
my $path = $u->path // '';
$path = '' if $path eq '/';
$u->path( '/.well-known/oauth-protected-resource' . $path );
return $u->as_string;
}
# Per-request engine built from config. Only the engine's own attrs are passed
# (StrictConstructor rejects the seam/metadata-only keys).
sub _oauth_rs_engine ( $c ) {
my $cfg = $c->_oauth_rs_config;
return Catalyst::Plugin::OAuth2::ResourceServer::Server->new(
map { exists $cfg->{$_} ? ( $_ => $cfg->{$_} ) : () }
qw/signing_key resource issuer jwt_alg leeway/
);
}
# Write a WWW-Authenticate: Bearer challenge. $err is an optional ...::Error.
sub oauth_challenge ( $c, $err = undef ) {
my $status = ( $err && $err->http_status ) ? $err->http_status : 401;
my @p;
push @p, sprintf( 'error="%s"', _oauth_rs_quote_hval( $err->error ) )
if $err && defined $err->error;
push @p,
sprintf( 'error_description="%s"',
_oauth_rs_quote_hval( $err->error_description ) )
if $err && defined $err->error_description;
( run in 1.572 second using v1.01-cache-2.11-cpan-5fbc6bb55f2 )