OAuth 2.0 authorization-server example
A minimal Catalyst app that mounts the plugin's authorization-server endpoints
(metadata, dynamic client registration, authorize, token) with an in-memory
Store and a fixed-user auto-consent hook. The client walks the full
authorization-code + PKCE (S256) flow: it dynamically registers a client,
drives the /oauth/authorize request, captures the redirected code, and
exchanges it at /oauth/token for a JWT access token.
Run it
plackup -p 5000 examples/app.psgi
perl examples/client.pl # or: perl examples/client.pl http://127.0.0.1:5000
Expected output
registered client_id=2rdgYIz_Fmef4h4ooaJreA
got authorization code=peipyr0wDuNt-8cadWiMPbTgRLLJyGpBjbvhTGEWZqk
access_token (JWT): eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJ1cm46ZXhhbXBsZTpyZXNvdXJjZSIsImV4cCI6MTc4NDEyMTg2NCwiaWF0IjoxNzg0MTIwOTY0LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJzY29wZSI6ImV4YW1wbGU6cmVhZCIsInN1YiI6ImRlbW8tdXNlciJ9.Dzew9--rhw0I48AcPg_H0wKrUVukCX9uEP3EZ4_D9dw
token_type=Bearer expires_in=900 scope=example:read
client_id, the authorization code, and the JWT are freshly generated on
every run, so the exact values above will differ between runs; the shape
(a client_id, a code, then a JWT access_token with expires_in=900 and
scope=example:read) is what to expect.