Catalyst-Plugin-OAuth2-AuthorizationServer
view release on metacpan or search on metacpan
t/server-token.t view on Meta::CPAN
use v5.36;
use Test::More;
use Test::Fatal;
use lib 't/lib';
use StubStore;
use Digest::SHA qw/sha256/;
use MIME::Base64 qw/encode_base64url/;
use Crypt::JWT qw/decode_jwt/;
my $class = 'Catalyst::Plugin::OAuth2::AuthorizationServer::Server';
require_ok($class);
my $key = 'k' x 32;
# RFC 7636 4.1 code verifiers: 43-128 chars of [A-Za-z0-9._~-]
my $VERIFIER = 'pkce-verifier-' . ( '0' x 29 );
my $VERIFIER2 = 'other-verifier-' . ( '1' x 28 );
my $CHALLENGE = encode_base64url( sha256($VERIFIER) );
sub fresh_engine { return $class->new(
store => StubStore->new, signing_key => $key,
issuer => 'https://as', resource => 'https://rs/mcp',
) }
# helper: drive authorize -> issue_code with a real PKCE pair
sub mint_code ( $eng, $verifier ) {
my $challenge = encode_base64url( sha256($verifier) );
$eng->store->create_client({
client_id => 'c1', redirect_uris => ['https://app/cb'] });
my $rid = $eng->validate_authorize({
client_id => 'c1', redirect_uri => 'https://app/cb',
response_type => 'code', code_challenge => $challenge,
code_challenge_method => 'S256', scope => 'example:read',
resource => 'https://rs/mcp',
})->{request_id};
return $eng->issue_code( 'user-9', $rid )->{code};
}
# happy path: code -> Bearer token (claims) + refresh token
{
my $eng = fresh_engine();
my $code = mint_code( $eng, $VERIFIER );
my $tok = $eng->exchange_authorization_code({
grant_type => 'authorization_code',
code => $code,
redirect_uri => 'https://app/cb',
code_verifier => $VERIFIER,
});
is( $tok->{token_type}, 'Bearer', 'Bearer token_type' );
is( $tok->{expires_in}, 900, 'expires_in = access_ttl' );
is( $tok->{scope}, 'example:read', 'scope echoed' );
ok( length $tok->{refresh_token}, 'refresh token issued' );
my $claims = decode_jwt( token => $tok->{access_token}, key => $key );
is( $claims->{sub}, 'user-9', 'sub claim' );
is( $claims->{aud}, 'https://rs/mcp', 'aud = resource' );
is( $claims->{scope}, 'example:read', 'scope claim' );
}
# PKCE mismatch -> invalid_grant
{
my $eng = fresh_engine();
my $code = mint_code( $eng, $VERIFIER );
( run in 1.586 second using v1.01-cache-2.11-cpan-54e63673c56 )