NAME
Punk::OAuth2::Presets - provider presets for Punk::OAuth2
SYNOPSIS
package MyApp;
use Punk;
use Punk::Plugin::OAuth2;
plugin 'OAuth2';
# a preset supplies the endpoints; you supply the credentials
oauth2 google => {
preset => 'google',
client_id => secret('oauth.google_id'),
client_secret => secret('oauth.google_secret'),
};
# any preset field can be replaced alongside it
oauth2 github => {
preset => 'github',
scope => 'read:user user:email repo',
client_id => secret('oauth.github_id'),
client_secret => secret('oauth.github_secret'),
};
# the config a preset expands to, if you want to see it
my $cfg = Punk::OAuth2::Presets::preset('google');
DESCRIPTION
A preset is a named bundle of provider configuration: the endpoints, default scope and client-authentication style for a provider whose details are fixed and public, so that declaring it takes a client id and secret rather than six URLs copied from someone's documentation.
Presets are built in C (include/pox/pox_presets.h) and handed to the provider constructor, which merges them under your own configuration. Nothing here is required: a provider declared without preset works exactly the same way, you just write the endpoints out yourself.
FUNCTIONS
preset
my $cfg = Punk::OAuth2::Presets::preset($name);
Returns a fresh hashref of configuration for $name, which is google, github or oidc. Not exported, and rarely called directly - the usual route is preset => $name in a provider declaration, which calls this for you. The hashref is newly built on every call, so modifying it cannot affect any other provider.
Croaks on an unknown name.
PRESETS
OpenID Connect against Google, with the endpoints hard-coded rather than discovered, so a login costs no discovery round trip:
oidc 1
issuer https://accounts.google.com
authorization_endpoint https://accounts.google.com/o/oauth2/v2/auth
token_endpoint https://oauth2.googleapis.com/token
jwks_uri https://www.googleapis.com/oauth2/v3/certs
userinfo_endpoint https://openidconnect.googleapis.com/v1/userinfo
scope openid email profile
auth_method body
Identity comes from the verified id_token, as for any OIDC provider.
github
GitHub is not an OpenID Connect provider: there is no id_token and no jwks_uri, so identity is fetched from the user API with the access token instead.
oidc 0
authorization_endpoint https://github.com/login/oauth/authorize
token_endpoint https://github.com/login/oauth/access_token
identity_endpoint https://api.github.com/user
emails_endpoint https://api.github.com/user/emails
scope read:user user:email
auth_method body
token_headers { Accept => 'application/json' }
identity_map \&Punk::OAuth2::_github_identity
token_headers is not decoration: GitHub's token endpoint answers in application/x-www-form-urlencoded unless asked for JSON.
The separate emails_endpoint exists because GET /user omits the email address whenever the account keeps it private, which is the default. See "IDENTITY MAPPING" for how the two responses are combined.
oidc
The generic case - no endpoints at all, just the two switches that tell the provider to find them itself:
oidc 1
discovery 1
Set issuer alongside it and everything else is read from that issuer's RFC 8414 / OpenID Connect discovery document. This is the preset to reach for with any standards-compliant identity provider that is not Google.
oauth2 corp => {
preset => 'oidc',
issuer => 'https://idp.corp.example',
client_id => '...',
client_secret => '...',
};
OVERRIDING
The provider constructor lays the preset down first and then your configuration on top, key by key, with the preset key itself dropped. So any field above can simply be named again in the declaration to replace it:
oauth2 github => {
preset => 'github',
scope => 'read:user user:email repo', # replaces the default
client_id => '...',
};
The merge is flat, not deep. Giving your own token_headers replaces the preset's hashref outright rather than adding to it, so carry over any part of it you still want:
token_headers => { Accept => 'application/json', 'X-Trace' => $id },
Fields no preset sets are filled in afterwards by the provider itself: auth_method defaults to basic, algs to RS256 and ES256, leeway to 60 seconds, scope to empty and discovery to off. That is why the two presets that want auth_method set it explicitly.
IDENTITY MAPPING
A plain OAuth2 provider - one with identity_endpoint rather than oidc - returns whatever shape its user API happens to use, so the provider needs a way to turn that into the normalized identity the rest of Punk::OAuth2 expects. That is identity_map: a coderef called with the decoded identity response and the decoded emails response (undef when there is no emails_endpoint, or it did not answer 200), returning a hashref that is merged into the identity.
identity_map => sub {
my ($user, $emails) = @_;
return { sub => $user->{uid}, email => $user->{mail} };
},
The github preset points this at Punk::OAuth2::_github_identity, an XSUB that produces:
sub-
$user->{id}, stringified. GitHub sends it as a number, and an identity that changes type between JSON decoders is a subtle way to lose a session. email-
The primary address from the emails response, or the first one it lists if none is flagged primary, falling back to
$user->{email}when the emails endpoint gave nothing. email_verified-
The
verifiedflag belonging to whichever address was chosen, orundefif the response did not say. name-
$user->{name}, falling back to$user->{login}- the display name is optional on GitHub and frequently unset. picture-
$user->{avatar_url}.
With no identity_map, the provider falls back to reading sub (or id), email and name straight off the identity response. Either way the untouched payload is always available as raw, so a mapping that drops a field costs you nothing.
SEE ALSO
Punk::Plugin::OAuth2 for the oauth2 declaration these presets are used from, and Punk::OAuth2::Provider for endpoint resolution, discovery and the full set of provider fields.
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)