File Coverage

blib/lib/OAuth/Lite2/Server/Endpoint/Token.pm
Criterion Covered Total %
statement 22 25 88.0
branch n/a
condition n/a
subroutine 8 9 88.8
pod n/a
total 30 34 88.2


line stmt bran cond sub pod time code
1             package OAuth::Lite2::Server::Endpoint::Token;
2              
3 5     5   6363 use strict;
  5         8  
  5         147  
4 5     5   21 use warnings;
  5         5  
  5         236  
5              
6             use overload
7 0     0   0 q(&{}) => sub { shift->psgi_app },
8 5     5   19 fallback => 1;
  5         6  
  5         42  
9              
10 5     5   2853 use Plack::Request;
  5         325052  
  5         193  
11 5     5   45 use Try::Tiny;
  5         7  
  5         307  
12 5     5   23 use Params::Validate;
  5         7  
  5         209  
13              
14 5     5   2105 use OAuth::Lite2::Server::Context;
  5         10  
  5         32  
15 5     5   1664 use OAuth::Lite2::Formatters;
  0            
  0            
16             use OAuth::Lite2::Server::Error;
17             use OAuth::Lite2::Server::GrantHandlers;
18              
19             sub new {
20             my $class = shift;
21             my %args = Params::Validate::validate(@_, {
22             data_handler => 1,
23             error_uri => { optional => 1 },
24             });
25             my $self = bless {
26             data_handler => $args{data_handler},
27             error_uri => $args{error_uri},
28             grant_handlers => {},
29             }, $class;
30             return $self;
31             }
32              
33             sub support_grant_type {
34             my ($self, $type) = @_;
35             my $handler = OAuth::Lite2::Server::GrantHandlers->get_handler($type)
36             or OAuth::Lite2::Server::Error::UnsupportedGrantType->throw;
37             $self->{grant_handlers}{$type} = $handler;
38             }
39              
40             sub support_grant_types {
41             my $self = shift;
42             $self->support_grant_type($_) for @_;
43             }
44              
45             sub data_handler {
46             my ($self, $handler) = @_;
47             $self->{data_handler} = $handler if $handler;
48             $self->{data_handler};
49             }
50              
51             sub psgi_app {
52             my $self = shift;
53             return $self->{psgi_app}
54             ||= $self->compile_psgi_app;
55             }
56              
57             sub compile_psgi_app {
58             my $self = shift;
59              
60             my $app = sub {
61             my $env = shift;
62             my $req = Plack::Request->new($env);
63             my $res; try {
64             $res = $self->handle_request($req);
65             } catch {
66             # Internal Server Error
67             warn $_;
68             $res = $req->new_response(500);
69             };
70             return $res->finalize;
71             };
72              
73             return $app;
74             }
75              
76             sub handle_request {
77             my ($self, $request) = @_;
78              
79             # from draft-v8, format is specified to JSON only.
80             my $format = "json";
81             # my $format = $request->param("format") || "json";
82             my $formatter = OAuth::Lite2::Formatters->get_formatter_by_name($format)
83             || OAuth::Lite2::Formatters->get_formatter_by_name("json");
84              
85             my $res = try {
86              
87             my $type = $request->param("grant_type")
88             or OAuth::Lite2::Server::Error::InvalidRequest->throw(
89             description => q{'grant_type' not found},
90             );
91              
92             my $handler = $self->{grant_handlers}{$type}
93             or OAuth::Lite2::Server::Error::UnsupportedGrantType->throw;
94              
95             my $data_handler = $self->{data_handler}->new(request => $request);
96              
97             my $client_id = $request->param("client_id")
98             or OAuth::Lite2::Server::Error::InvalidRequest->throw(
99             description => q{'client_id' not found},
100             );
101              
102             my $client_secret = $request->param("client_secret")
103             or OAuth::Lite2::Server::Error::InvalidRequest->throw(
104             description => q{'client_secret' not found},
105             );
106              
107             $data_handler->validate_client($client_id, $client_secret, $type)
108             or OAuth::Lite2::Server::Error::InvalidClient->throw;
109              
110             my $result = $handler->handle_request($data_handler);
111              
112             return $request->new_response(200,
113             [ "Content-Type" => $formatter->type,
114             "Cache-Control" => "no-store" ],
115             [ $formatter->format($result) ]);
116              
117             } catch {
118              
119             if ($_->isa("OAuth::Lite2::Server::Error")) {
120              
121             my $error_params = { error => $_->type };
122             $error_params->{error_description} = $_->description
123             if $_->description;
124             $error_params->{error_uri} = $self->{error_uri}
125             if $self->{error_uri};
126              
127             return $request->new_response($_->code,
128             [ "Content-Type" => $formatter->type,
129             "Cache-Control" => "no-store" ],
130             [ $formatter->format($error_params) ]);
131              
132             } else {
133              
134             die $_;
135              
136             }
137              
138             };
139             }
140              
141             =head1 NAME
142              
143             OAuth::Lite2::Server::Endpoint::Token - token endpoint PSGI application
144              
145             =head1 SYNOPSIS
146              
147             token_endpoint.psgi
148              
149             use strict;
150             use warnings;
151             use Plack::Builder;
152             use OAuth::Lite2::Server::Endpoint::Token;
153             use MyDataHandlerClass;
154              
155             builder {
156             my $app = OAuth::Lite2::Server::Endpoint::Token->new(
157             data_handler => 'MyDataHandlerClass',
158             );
159             $app->support_grant_types(qw(authorization_code refresh_token));
160             $app;
161             };
162              
163             =head1 DESCRIPTION
164              
165             The object of this class behaves as PSGI application (subroutine reference).
166             This is for OAuth 2.0 token-endpoint.
167              
168             At first you have to make your custom class inheriting L,
169             and setup PSGI file with it.
170              
171             =head1 METHODS
172              
173             =head2 new( %params )
174              
175             =over 4
176              
177             =item data_handler
178              
179             name of your custom class that inherits L
180             and implements interface.
181              
182             =item error_uri
183              
184             Optional. URI that represents error description page.
185             This would be included in error responses.
186              
187             =back
188              
189             =head2 support_grant_type( $type )
190              
191             =head2 support_grant_types( @types )
192              
193             You can set 'authorization_code', 'password', or 'refresh_token'
194              
195             =head2 data_handler
196              
197             =head2 psgi_app
198              
199             =head2 compile_psgi_app
200              
201             =head2 handle_request( $req )
202              
203             =head1 TEST
204              
205             You can test with L and some of client classes.
206              
207             my $app = OAuth::Lite2::Server::Endpoint::Token->new(
208             data_handler => 'MyDataHandlerClass',
209             );
210             $app->support_grant_types(qw(authorization_code refresh_token));
211             my $mock_agent = OAuth::Lite2::Agent::PSGIMock->new(app => $app);
212             my $client = OAuth::Lite2::Client::UsernameAndPassword->new(
213             id => q{my_client_id},
214             secret => q{my_client_secret},
215             agent => $mock_agent,
216             );
217             my $token = $client->get_access_token(
218             username => q{foo},
219             password => q{bar},
220             );
221             ok($token);
222             is($token->access_token, q{access_token_value});
223              
224             =head1 AUTHOR
225              
226             Lyo Kato, Elyo.kato@gmail.comE
227              
228             =head1 COPYRIGHT AND LICENSE
229              
230             Copyright (C) 2010 by Lyo Kato
231              
232             This library is free software; you can redistribute it and/or modify
233             it under the same terms as Perl itself, either Perl version 5.8.8 or,
234             at your option, any later version of Perl 5 you may have available.
235              
236             =cut
237              
238             1;