.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" 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 .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "LWP::Authen::OAuth2::ServiceProvider 3pm" .TH LWP::Authen::OAuth2::ServiceProvider 3pm "2021-01-11" "perl v5.32.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" LWP::Authen::OAuth2::ServiceProvider \- ServiceProvider base class .SH "VERSION" .IX Header "VERSION" version 0.18 .SH "SYNOPSIS" .IX Header "SYNOPSIS" This is a base module for representing an OAuth 2 service provider. It is implicitly constructed from the parameters to \f(CW\*(C`LWP::Authen::OAuth2\->new\*(C'\fR, and is automatically delegated to when needed. .PP The first way to try to specify the service provider is with the parameters \&\f(CW\*(C`service_provider\*(C'\fR and possibly \f(CW\*(C`client_type\*(C'\fR: .PP .Vb 6 \& LWP::Authen::OAuth2\->new( \& ... \& service_provider => "Foo", \& client_type => "bar", # optional \& ... \& ); .Ve .PP The first parameter will cause LWP::Authen::OAuth2::ServiceProvider to look for either \f(CW\*(C`LWP::Authen::OAuth2::ServiceProvider::Foo\*(C'\fR, or if that is not found, for \f(CW\*(C`Foo\*(C'\fR. (If neither is present, an exception will be thrown.) The second parameter will be passed to that module which can choose to customize the service provider behavior based on the client_type. .PP The other way to specify the service provider is by passing in sufficient parameters to create a custom one on the fly: .PP .Vb 4 \& LWP::Authen::OAuth2\->new( \& ... \& authorization_endpoint => $authorization_endpoint, \& token_endpoint => $token_endpoint, \& \& # These are optional but let you get the typo checks of strict mode \& authorization_required_params => [...], \& authorization_optional_params => [...], \& ... \& ); .Ve .PP See LWP::Authen::OAuth2::Overview if you are uncertain how to figure out the \fIAuthorization Endpoint\fR and \fIToken Endpoint\fR from the service provider's documentation. .SH "KNOWN SERVICE PROVIDERS" .IX Header "KNOWN SERVICE PROVIDERS" The following service providers are provided in this distribution, with hopefully useful configuration and documentation: .IP "LWP::Authen::OAuth2::ServiceProvider::Dwolla" 4 .IX Item "LWP::Authen::OAuth2::ServiceProvider::Dwolla" .PD 0 .IP "LWP::Authen::OAuth2::ServiceProvider::Google" 4 .IX Item "LWP::Authen::OAuth2::ServiceProvider::Google" .IP "LWP::Authen::OAuth2::ServiceProvider::Line" 4 .IX Item "LWP::Authen::OAuth2::ServiceProvider::Line" .IP "LWP::Authen::OAuth2::ServiceProvider::Strava" 4 .IX Item "LWP::Authen::OAuth2::ServiceProvider::Strava" .IP "LWP::Authen::OAuth2::ServiceProvider::Yahoo" 4 .IX Item "LWP::Authen::OAuth2::ServiceProvider::Yahoo" .PD .SH "SUBCLASSING" .IX Header "SUBCLASSING" Support for new service providers can be added with subclasses. To do that it is useful to understand how things get delegated under the hood. .PP First LWP::Authen::OAuth2 asks LWP::Authen::OAuth2::ServiceProvider to construct a service provider. Based on the \f(CW\*(C`service_provider\*(C'\fR argument, it figures out that it needs to load and use your base class. A service provider might need different behaviors for different client types. You are free to take the client type and dynamically decide which subclass of yours will be loaded instead to get the correct flow. Should your subclass need to, it can decide that that a subclass of LWP::Authen::OAuth2 should be used that actually knows about request types that are specific to your service provider. Hopefully most service providers do not need this, but some do. .PP For all of the potential complexity that is supported, \fBmost\fR service provider subclasses should be simple. Just state what fields differ from the specification for specific requests and client types, then include documentation. However even crazy service providers should be supportable. .PP Here are the methods that were designed to be useful to override. See the source if you have a need that none of these address. But if you can do what you need to do through these, please do. .ie n .IP """authorization_endpoint""" 4 .el .IP "\f(CWauthorization_endpoint\fR" 4 .IX Item "authorization_endpoint" Takes no arguments, returns the \s-1URL\s0 for the Authorization Endpoint for the service provider. Your subclass cannot function without this. .ie n .IP """token_endpoint""" 4 .el .IP "\f(CWtoken_endpoint\fR" 4 .IX Item "token_endpoint" Takes no arguments, returns the \s-1URL\s0 for the Token Endpoint for the service provider. Your subclass cannot function without this. .ie n .IP """client_type_class""" 4 .el .IP "\f(CWclient_type_class\fR" 4 .IX Item "client_type_class" This method receives your class name and the passed in \f(CW\*(C`client_type\*(C'\fR. It is supposed to make sure that the class that handles that \&\f(CW\*(C`client_type\*(C'\fR is loaded, and then return it. This lets you handle service providers with different behavior for different types of clients. .Sp The base implementation just returns your class name. .Sp If the programmer does not pass an explicit \f(CW\*(C`client_type\*(C'\fR the value that is passed in is \f(CW\*(C`default\*(C'\fR. So that should be mapped to a reasonable client type. This likely is something along the line of \*(L"webserver\*(R". That way your module can be used without specifying a \f(CW\*(C`client_type\*(C'\fR. .ie n .IP """init""" 4 .el .IP "\f(CWinit\fR" 4 .IX Item "init" After \f(CW\*(C`new\*(C'\fR has figured out the right class to load, it immediately calls \&\f(CW\*(C`$self\-e with \f(CW$opts\fR being a hashref of all options passed to \f(CW\*(C`LWP::Authen::OAuth2\->new(...)\*(C'\fR that were not consumed in figuring out the service provider. This method can then extract any parameters that it wants to before anything else happens. .Sp If you only want to require/allow a few parameters to be extracted into the service provider object, then there is no need to write your own \f(CW\*(C`init\*(C'\fR. But if you want additional logic depending on passed in parameters, you can. .Sp To consume options and copy them to \f(CW$self\fR please use the following methods: .Sp .Vb 2 \& $self\->copy_option($opts, $required_field); \& $self\->copy_option($opts, $optional_field, $default); .Ve .Sp If you want to consume options and return them as values instead: .Sp .Vb 2 \& my $value1 = $self\->extract_option($opts, $required_field); \& my $value2 = $self\->extract_option($opts, $optional_field, $default); .Ve .Sp These methods delete from the hash, so do not try to consume an option twice. .ie n .IP """required_init""" 4 .el .IP "\f(CWrequired_init\fR" 4 .IX Item "required_init" The parameters that must be passed into \f(CW\*(C`LWP::Authen::OAuth2\->new(...)\*(C'\fR to initialize the service provider object. The default required parameters are \f(CW\*(C`client_id\*(C'\fR and \f(CW\*(C`client_secret\*(C'\fR, which in turn get used as default arguments inside of methods that need them. In general it is good to only require arguments that are needed to generate refreshed tokens. If you will not get a \f(CW\*(C`refresh_token\*(C'\fR in your flow, then you should require nothing. .ie n .IP """optional_init""" 4 .el .IP "\f(CWoptional_init\fR" 4 .IX Item "optional_init" The parameters that can be passed into \f(CW\*(C`LWP::Authen::OAuth2\->new(...)\*(C'\fR to initialize the service provider object. The default optional parameters are \&\f(CW\*(C`redirect_uri\*(C'\fR and \f(CW\*(C`scope\*(C'\fR which, if passed, do not have to be passed into other method calls. .Sp The \f(CW\*(C`state\*(C'\fR is not included as an explicit hint that you should not simply use a default value. .Sp Note that these lists are deduped, so there is no harm in parameters being both required and optional, or appearing multiple times. .ie n .IP """{authorization,request,refresh}_required_params""" 4 .el .IP "\f(CW{authorization,request,refresh}_required_params\fR" 4 .IX Item "{authorization,request,refresh}_required_params" These three methods list parameters that \fBmust\fR be included in the authorization url, the post to request tokens, and the post to refresh tokens respectively. Supplying these can give better error messages if they are left out. .ie n .IP """{authorization,request,refresh}_optional_params""" 4 .el .IP "\f(CW{authorization,request,refresh}_optional_params\fR" 4 .IX Item "{authorization,request,refresh}_optional_params" These three methods list parameters that \fBcan\fR be included in the authorization url, the post to request tokens, and the post to refresh tokens respectively. In strict mode, supplying any parameters not included in more or required params will be an error. Otherwise this has little effect. .ie n .IP """{authorization,request,refresh}_default_params""" 4 .el .IP "\f(CW{authorization,request,refresh}_default_params\fR" 4 .IX Item "{authorization,request,refresh}_default_params" These three methods returns a list of key/value pairs mapping parameters to \&\fBdefault\fR values in the authorization url, the post to request tokens, and the post to get refreshed tokens respectively. Supplying these can stop people from having to supply the parameters themselves. .Sp An example where this could be useful is to support a flow that uses different types of requests than normal. For example with some client types and service providers, you might use a type of request with a \&\f(CW\*(C`grant_type\*(C'\fR of \f(CW\*(C`password\*(C'\fR or \f(CW\*(C`client_credentials\*(C'\fR. .ie n .IP """post_to_token_endpoint""" 4 .el .IP "\f(CWpost_to_token_endpoint\fR" 4 .IX Item "post_to_token_endpoint" When a post to a token endpoint is constructed, this actually sends the request. The specification allows service providers to require authentication beyond what the specification requires, which may require cookies, specific headers, etc. This method allows you to address that case. .ie n .IP """access_token_class""" 4 .el .IP "\f(CWaccess_token_class\fR" 4 .IX Item "access_token_class" Given a \f(CW\*(C`token_type\*(C'\fR, what class implements access tokens of that type? If your provider creates a new token type, or implements an existing token type in a quirky way that requires a nonstandard model to handle, this method can let you add support for that. .Sp The specification says that all the \f(CW\*(C`token_type\*(C'\fR must be case insensitive, so all types are lower cased for you. .Sp If the return value does not look like a package name, it is assumed to be an error message. As long as you have spaces in your error messages and normal looking class names, this should \s-1DWIM.\s0 .Sp See LWP::Authen::OAuth2::AccessToken for a description of the interface that your access token class needs to meet. (You do not have to subclass that \- just duck typing here.) .ie n .IP """oauth2_class""" 4 .el .IP "\f(CWoauth2_class\fR" 4 .IX Item "oauth2_class" Override this to cause \f(CW\*(C`LWP::Authen::OAuth2\->new(...)\*(C'\fR to return an object in a custom class. This would be appropriate if people using your service provider need methods exposed that are not in LWP::Authen::OAuth2. .Sp Few service provider classes should find a reason to do this, but it can be done if you need. .ie n .IP """collect_action_params""" 4 .el .IP "\f(CWcollect_action_params\fR" 4 .IX Item "collect_action_params" This is the method that processes parameters for a given action. Should your service provider support a new kind of request, you can use this along with the \f(CW\*(C`*_{required,more,default}_params\*(C'\fR functions to support it. .Sp The implementation of \f(CW\*(C`request_tokens\*(C'\fR in this module give an example of how to use it. .SH "CONTRIBUTING" .IX Header "CONTRIBUTING" Patches contributing new service provider subclasses to this distributions are encouraged. Should you wish to do so, please submit a git pull request that does the following: .IP "Implement your provider" 4 .IX Item "Implement your provider" The more completely implemented, the better. .IP "Name it properly" 4 .IX Item "Name it properly" The name should be of the form: .Sp .Vb 1 \& LWP::Authen::OAuth2::ServiceProvider::$ServiceProvider .Ve .IP "List it" 4 .IX Item "List it" It needs to be listed as a known service provider in this module. .IP "Test it" 4 .IX Item "Test it" It is impossible to usefully test a service provider module without client secrets. However you can have public tests that it compiles, and private tests that will, if someone supplies the necessary secrets, run fuller tests that all works. See the existing unit tests for examples. .IP "Include it" 4 .IX Item "Include it" Your files need to be included in the \f(CW\*(C`MANIFEST\*(C'\fR in the root directory. .IP "Document Client Registration" 4 .IX Item "Document Client Registration" A developer should be able to read your module and know how to register themselves as a client of the service provider. .IP "List Client Types" 4 .IX Item "List Client Types" Please list the client types that the service provider uses, with just enough detail that a developer can figure out which one to use. Listed types should, of course, either be implemented or be documented as not implemented. .IP "Document important quirks" 4 .IX Item "Document important quirks" If the service provider requires or allows useful parameters, try to mention them in your documentation. .IP "Document limitations" 4 .IX Item "Document limitations" If there are known limitations in your implementation, please state them. .IP "Link to official documentation" 4 .IX Item "Link to official documentation" If the service provider provides official OAuth 2 documentation, please link to it. Ideally a developer will not need to refer to it, but should know how to find it. .SH "AUTHORS" .IX Header "AUTHORS" .IP "\(bu" 4 Ben Tilly, .IP "\(bu" 4 Thomas Klausner .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2013 \- 2021 by Ben Tilly, Rent.com, Thomas Klausner. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.