.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Mojolicious::Plugin::OAuth2 3pm" .TH Mojolicious::Plugin::OAuth2 3pm "2022-02-12" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Mojolicious::Plugin::OAuth2 \- Auth against OAuth2 APIs including OpenID Connect .SH "SYNOPSIS" .IX Header "SYNOPSIS" .SS "Example application" .IX Subsection "Example application" .Vb 1 \& use Mojolicious::Lite; \& \& plugin OAuth2 => { \& providers => { \& facebook => { \& key => \*(Aqsome\-public\-app\-id\*(Aq, \& secret => $ENV{OAUTH2_FACEBOOK_SECRET}, \& }, \& }, \& }; \& \& get \*(Aq/connect\*(Aq => sub { \& my $c = shift; \& my %get_token = (redirect_uri => $c\->url_for(\*(Aqconnect\*(Aq)\->userinfo(undef)\->to_abs); \& \& return $c\->oauth2\->get_token_p(facebook => \e%get_token)\->then(sub { \& # Redirected to Facebook \& return unless my $provider_res = shift; \& \& # Token received \& $c\->session(token => $provider_res\->{access_token}); \& $c\->redirect_to(\*(Aqprofile\*(Aq); \& })\->catch(sub { \& $c\->render(\*(Aqconnect\*(Aq, error => shift); \& }); \& }; .Ve .PP See \*(L"register\*(R" for more details about the configuration this plugin takes. .SS "Testing" .IX Subsection "Testing" Code using this plugin can perform offline testing, using the \*(L"mocked\*(R" provider: .PP .Vb 3 \& $app\->plugin(OAuth2 => {mocked => {key => 42}}); \& $app\->routes\->get(\*(Aq/profile\*(Aq => sub { \& my $c = shift; \& \& state $mocked = $ENV{TEST_MOCKED} && \*(Aqmocked\*(Aq; \& return $c\->oauth2\->get_token_p($mocked || \*(Aqfacebook\*(Aq)\->then(sub { \& ... \& }); \& }); .Ve .PP See Mojolicious::Plugin::OAuth2::Mock for more details. .SS "Connect button" .IX Subsection "Connect button" You can add a \*(L"connect link\*(R" to your template using the \*(L"oauth2.auth_url\*(R" helper. Example template: .PP .Vb 2 \& Click here to log in: \& <%= link_to \*(AqConnect!\*(Aq, $c\->oauth2\->auth_url(\*(Aqfacebook\*(Aq, scope => \*(Aquser_about_me email\*(Aq) %> .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This Mojolicious plugin allows you to easily authenticate against a OAuth2 or OpenID Connect provider. It includes configurations for a few popular providers, but you can add your own as well. .PP See \*(L"register\*(R" for a full list of bundled providers. .PP To support \*(L"OpenID Connect\*(R", the following optional modules must be installed manually: Crypt::OpenSSL::Bignum, Crypt::OpenSSL::RSA and Mojo::JWT. The modules can be installed with App::cpanminus: .PP .Vb 1 \& $ cpanm Crypt::OpenSSL::Bignum Crypt::OpenSSL::RSA Mojo::JWT .Ve .SH "HELPERS" .IX Header "HELPERS" .SS "oauth2.auth_url" .IX Subsection "oauth2.auth_url" .Vb 1 \& $url = $c\->oauth2\->auth_url($provider_name => \e%args); .Ve .PP Returns a Mojo::URL object which contain the authorize \s-1URL.\s0 This is useful if you want to add the authorize \s-1URL\s0 as a link to your webpage instead of doing a redirect like \*(L"oauth2.get_token\*(R" does. \f(CW%args\fR is optional, but can contain: .IP "\(bu" 2 host .Sp Useful if your provider uses different hosts for accessing different accounts. The default is specified in the provider configuration. .Sp .Vb 1 \& $url\->host($host); .Ve .IP "\(bu" 2 authorize_query .Sp Either a hash-ref or an array-ref which can be used to give extra query params to the \s-1URL.\s0 .Sp .Vb 1 \& $url\->query($authorize_url); .Ve .IP "\(bu" 2 redirect_uri .Sp Useful if you want to go back to a different page than what you came from. The default is: .Sp .Vb 1 \& $c\->url_for\->to_abs\->to_string .Ve .IP "\(bu" 2 scope .Sp Scope to ask for credentials to. Should be a space separated list. .IP "\(bu" 2 state .Sp A string that will be sent to the identity provider. When the user returns from the identity provider, this exact same string will be carried with the user, as a \s-1GET\s0 parameter called \f(CW\*(C`state\*(C'\fR in the \s-1URL\s0 that the user will return to. .SS "oauth2.get_refresh_token_p" .IX Subsection "oauth2.get_refresh_token_p" .Vb 1 \& $promise = $c\->oauth2\->get_refresh_token_p($provider_name => \e%args); .Ve .PP When Mojolicious::Plugin::OAuth2 is being used in OpenID Connect mode this helper allows for a token to be refreshed by specifying a \f(CW\*(C`refresh_token\*(C'\fR in \&\f(CW%args\fR. Usage is similar to \*(L"oauth2.get_token_p\*(R". .SS "oauth2.get_token_p" .IX Subsection "oauth2.get_token_p" .Vb 3 \& $promise = $c\->oauth2\->get_token_p($provider_name => \e%args) \& \->then(sub { my $provider_res = shift }) \& \->catch(sub { my $err = shift; }); .Ve .PP \&\*(L"oauth2.get_token_p\*(R" is used to either fetch an access token from an OAuth2 provider, handle errors or redirect to OAuth2 provider. \f(CW$err\fR in the rejection handler holds a error description if something went wrong. \&\f(CW$provider_res\fR is a hash-ref containing the access token from the OAauth2 provider or \f(CW\*(C`undef\*(C'\fR if this plugin performed a 302 redirect to the provider's connect website. .PP In more detail, this method will do one of two things: .IP "1." 2 When called from an action on your site, it will redirect you to the provider's \&\f(CW\*(C`authorize_url\*(C'\fR. This site will probably have some sort of \*(L"Connect\*(R" and \&\*(L"Reject\*(R" button, allowing the visitor to either connect your site with his/her profile on the OAuth2 provider's page or not. .IP "2." 2 The OAuth2 provider will redirect the user back to your site after clicking the \&\*(L"Connect\*(R" or \*(L"Reject\*(R" button. \f(CW$provider_res\fR will then contain a key \&\*(L"access_token\*(R" on \*(L"Connect\*(R" and a false value on \*(L"Reject\*(R". .PP The method takes these arguments: \f(CW$provider_name\fR need to match on of the provider names under \*(L"Configuration\*(R" or a custom provider defined when registering the plugin. .PP \&\f(CW%args\fR can have: .IP "\(bu" 2 host .Sp Useful if your provider uses different hosts for accessing different accounts. The default is specified in the provider configuration. .IP "\(bu" 2 redirect .Sp Set \f(CW\*(C`redirect\*(C'\fR to 0 to disable automatic redirect. .IP "\(bu" 2 scope .Sp Scope to ask for credentials to. Should be a space separated list. .SS "oauth2.jwt_decode" .IX Subsection "oauth2.jwt_decode" .Vb 2 \& $claims = $c\->oauth2\->jwt_decode($provider, sub { my $jwt = shift; ... }); \& $claims = $c\->oauth2\->jwt_decode($provider); .Ve .PP When Mojolicious::Plugin::OAuth2 is being used in OpenID Connect mode this helper allows you to decode the response data encoded with the \s-1JWKS\s0 discovered from \f(CW\*(C`well_known_url\*(C'\fR configuration. .SS "oauth2.logout_url" .IX Subsection "oauth2.logout_url" .Vb 1 \& $url = $c\->oauth2\->logout_url($provider_name => \e%args); .Ve .PP When Mojolicious::Plugin::OAuth2 is being used in OpenID Connect mode this helper creates the url to redirect to end the session. The OpenID Connect Provider will redirect to the \f(CW\*(C`post_logout_redirect_uri\*(C'\fR provided in \f(CW%args\fR. Additional keys for \f(CW%args\fR are \f(CW\*(C`id_token_hint\*(C'\fR and \f(CW\*(C`state\*(C'\fR. .SS "oauth2.providers" .IX Subsection "oauth2.providers" .Vb 1 \& $hash_ref = $c\->oauth2\->providers; .Ve .PP This helper allow you to access the raw providers mapping, which looks something like this: .PP .Vb 9 \& { \& facebook => { \& authorize_url => "https://graph.facebook.com/oauth/authorize", \& token_url => "https://graph.facebook.com/oauth/access_token", \& key => ..., \& secret => ..., \& }, \& ... \& } .Ve .SH "ATTRIBUTES" .IX Header "ATTRIBUTES" .SS "providers" .IX Subsection "providers" .Vb 1 \& $hash_ref = $oauth2\->providers; .Ve .PP Holds a hash of provider information. See \*(L"oauth2.providers\*(R". .SH "METHODS" .IX Header "METHODS" .SS "register" .IX Subsection "register" .Vb 2 \& $app\->plugin(OAuth2 => \e%provider_config); \& $app\->plugin(OAuth2 => {providers => \e%provider_config, proxy => 1, ua => Mojo::UserAgent\->new}); .Ve .PP Will register this plugin in your application with a given \f(CW%provider_config\fR. The keys in \f(CW%provider_config\fR are provider names and the values are configuration for each provider. Note that the value will be merged with the predefined providers below. .PP Instead of just passing in \f(CW%provider_config\fR, it is possible to pass in a more complex config, with these keys: .IP "\(bu" 2 providers .Sp The \f(CW%provider_config\fR must be present under this key. .IP "\(bu" 2 proxy .Sp Setting this to a true value will automatically detect proxy settings using \&\*(L"detect\*(R" in Mojo::UserAgent::Proxy. .IP "\(bu" 2 ua .Sp A custom Mojo::UserAgent, in case you want to change proxy settings, timeouts or other attributes. .PP Instead of just passing in \f(CW%provider_config\fR, it is possible to pass in a hash-ref \*(L"providers\*(R" (\f(CW%provider_config\fR) and \*(L"ua\*(R" (a custom Mojo::UserAgent object). .PP Here is an example to add adddition information like \*(L"key\*(R" and \*(L"secret\*(R": .PP .Vb 10 \& $app\->plugin(OAuth2 => { \& providers => { \& custom_provider => { \& key => \*(AqAPP_ID\*(Aq, \& secret => \*(AqSECRET_KEY\*(Aq, \& authorize_url => \*(Aqhttps://provider.example.com/auth\*(Aq, \& token_url => \*(Aqhttps://provider.example.com/token\*(Aq, \& }, \& github => { \& key => \*(AqAPP_ID\*(Aq, \& secret => \*(AqSECRET_KEY\*(Aq, \& }, \& }, \& }); .Ve .PP For OpenID Connect , \f(CW\*(C`authorize_url\*(C'\fR and \f(CW\*(C`token_url\*(C'\fR are configured from the \&\f(CW\*(C`well_known_url\*(C'\fR so these are replaced by the \f(CW\*(C`well_known_url\*(C'\fR key. .PP .Vb 9 \& $app\->plugin(OAuth2 => { \& providers => { \& azure_ad => { \& key => \*(AqAPP_ID\*(Aq, \& secret => \*(AqSECRET_KEY\*(Aq, \& well_known_url => \*(Aqhttps://login.microsoftonline.com/tenant\-id/v2.0/.well\-known/openid\-configuration\*(Aq, \& }, \& }, \& }); .Ve .PP To make it a bit easier the are already some predefined providers bundled with this plugin: .PP \fIdailymotion\fR .IX Subsection "dailymotion" .PP Authentication for video site. .PP \fIdebian_salsa\fR .IX Subsection "debian_salsa" .PP Authentication for . .PP \fIeventbrite\fR .IX Subsection "eventbrite" .PP Authentication for event site. .PP See also . .PP \fIfacebook\fR .IX Subsection "facebook" .PP OAuth2 for Facebook's graph \s-1API,\s0 . You can find \&\f(CW\*(C`key\*(C'\fR (App \s-1ID\s0) and \f(CW\*(C`secret\*(C'\fR (App Secret) from the app dashboard here: . .PP See also . .PP \fIinstagram\fR .IX Subsection "instagram" .PP OAuth2 for Instagram \s-1API.\s0 You can find \f(CW\*(C`key\*(C'\fR (Client \s-1ID\s0) and \&\f(CW\*(C`secret\*(C'\fR (Client Secret) from the app dashboard here: . .PP See also . .PP \fIgithub\fR .IX Subsection "github" .PP Authentication with Github. .PP See also . .PP \fIgoogle\fR .IX Subsection "google" .PP OAuth2 for Google. You can find the \f(CW\*(C`key\*(C'\fR (\s-1CLIENT ID\s0) and \f(CW\*(C`secret\*(C'\fR (\s-1CLIENT SECRET\s0) from the app console here under \*(L"APIs & Auth\*(R" and \&\*(L"Credentials\*(R" in the menu at . .PP See also . .PP \fIvkontakte\fR .IX Subsection "vkontakte" .PP OAuth2 for Vkontakte. You can find \f(CW\*(C`key\*(C'\fR (App \s-1ID\s0) and \f(CW\*(C`secret\*(C'\fR (Secure key) from the app dashboard here: . .PP See also . .SH "AUTHOR" .IX Header "AUTHOR" Marcus Ramberg \- \f(CW\*(C`mramberg@cpan.org\*(C'\fR .PP Jan Henning Thorsen \- \f(CW\*(C`jhthorsen@cpan.org\*(C'\fR .SH "LICENSE" .IX Header "LICENSE" This software is licensed under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "\(bu" 2 .IP "\(bu" 2 .IP "\(bu" 2 .IP "\(bu" 2 .IP "\(bu" 2