File Coverage

blib/lib/Plack/Middleware/Auth/OAuth2/ProtectedResource.pm
Criterion Covered Total %
statement 63 64 98.4
branch 24 32 75.0
condition 2 3 66.6
subroutine 12 12 100.0
pod 1 1 100.0
total 102 112 91.0


line stmt bran cond sub pod time code
1             package Plack::Middleware::Auth::OAuth2::ProtectedResource;
2              
3 2     2   4079 use strict;
  2         3  
  2         59  
4 2     2   9 use warnings;
  2         5  
  2         46  
5              
6 2     2   11 use parent 'Plack::Middleware';
  2         3  
  2         16  
7              
8 2     2   9617 use Plack::Request;
  2         5  
  2         44  
9 2     2   9 use Plack::Util::Accessor qw(realm data_handler error_uri);
  2         4  
  2         8  
10 2     2   83 use Try::Tiny;
  2         3  
  2         113  
11 2     2   11 use Carp ();
  2         4  
  2         27  
12              
13 2     2   9 use OAuth::Lite2::Server::Error;
  2         4  
  2         36  
14 2     2   626 use OAuth::Lite2::ParamMethods;
  2         5  
  2         1191  
15              
16             sub call {
17 34     34 1 4105737 my ($self, $env) = @_;
18 34         62 my $is_legacy = 0;
19              
20             my $error_res = try {
21              
22 34     34   1069 my $req = Plack::Request->new($env);
23              
24             # after draft-v6, signature is not required, so always each connection
25             # should be under TLS.
26             # warn "insecure bearere token request" unless $req->secure;
27              
28 34 50       472 my $parser = OAuth::Lite2::ParamMethods->get_param_parser($req)
29             or OAuth::Lite2::Server::Error::InvalidRequest->throw;
30              
31 34         5686 $is_legacy = $parser->is_legacy($req);
32              
33             # after draft-v6, $params aren't required.
34 34         340 my ($token, $params) = $parser->parse($req);
35 34 100       141 OAuth::Lite2::Server::Error::InvalidRequest->throw unless $token;
36              
37 30         228 my $dh = $self->{data_handler}->new(request => $req);
38              
39 30         112 my $access_token = $dh->get_access_token($token);
40              
41 30 100       816 OAuth::Lite2::Server::Error::InvalidToken->throw
42             unless $access_token;
43              
44 24 50       111 Carp::croak "OAuth::Lite2::Server::DataHandler::get_access_token doesn't return OAuth::Lite2::Model::AccessToken"
45             unless $access_token->isa("OAuth::Lite2::Model::AccessToken");
46              
47 24 100       68 unless ($access_token->created_on + $access_token->expires_in > time())
48             {
49 6 100       61 if($is_legacy){
50 3         52 OAuth::Lite2::Server::Error::ExpiredTokenLegacy->throw;
51             }else{
52 3         30 OAuth::Lite2::Server::Error::ExpiredToken->throw;
53             }
54             }
55              
56 18         187 my $auth_info = $dh->get_auth_info_by_id($access_token->auth_id);
57              
58 18 50       170 OAuth::Lite2::Server::Error::InvalidToken->throw
59             unless $auth_info;
60              
61 18 50       81 Carp::croak "OAuth::Lite2::Server::DataHandler::get_auth_info_by_id doesn't return OAuth::Lite2::Model::AuthInfo"
62             unless $auth_info->isa("OAuth::Lite2::Model::AuthInfo");
63              
64 18 100       62 $dh->validate_client_by_id($auth_info->client_id)
65             or OAuth::Lite2::Server::Error::InvalidToken->throw;
66              
67 12 100       132 $dh->validate_user_by_id($auth_info->user_id)
68             or OAuth::Lite2::Server::Error::InvalidToken->throw;
69              
70 6         56 $env->{REMOTE_USER} = $auth_info->user_id;
71 6         38 $env->{X_OAUTH_CLIENT} = $auth_info->client_id;
72 6 50       40 $env->{X_OAUTH_SCOPE} = $auth_info->scope if $auth_info->scope;
73             # pass legacy flag
74 6         63 $env->{X_OAUTH_IS_LEGACY} = ($is_legacy);
75              
76 6         31 return;
77              
78             } catch {
79              
80 28 50   28   511 if ($_->isa("OAuth::Lite2::Server::Error")) {
81              
82 28         31 my @params;
83 28 50       276 push(@params, sprintf(q{realm="%s"}, $self->{realm}))
84             if $self->{realm};
85 28         98 push(@params, sprintf(q{error="%s"}, $_->type));
86 28 100       124 push(@params, sprintf(q{error_description="%s"}, $_->description))
87             if $_->description;
88 28 50       93 push(@params, sprintf(q{error_uri="%s"}, $self->{error_uri}))
89             if $self->{error_uri};
90             # push(@params, sprintf(q{scope='%s'}, $_->scope))
91             # if $_->scope;
92              
93 28 100       59 if($is_legacy){
94 14         56 return [ $_->code, [ "WWW-Authenticate" =>
95             "OAuth " . join(', ', @params) ], [ ] ];
96             }else{
97 14         44 return [ $_->code, [ "WWW-Authenticate" =>
98             "Bearer " . join(', ', @params) ], [ ] ];
99             }
100              
101             } else {
102              
103             # rethrow
104 0         0 die $_;
105              
106             }
107              
108 34         352 };
109              
110 34   66     860 return $error_res || $self->app->($env);
111             }
112              
113             =head1 NAME
114              
115             Plack::Middleware::Auth::OAuth2::ProtectedResource - middleware for OAuth 2.0 Protected Resource endpoint
116              
117             =head1 SYNOPSIS
118              
119             my $app = sub {...};
120             builder {
121             enable "Plack::Middleware::Auth::OAuth2::ProtectedResource",
122             data_handler => "YourApp::DataHandler",
123             error_uri => q{http://example.org/error/description};
124             enable "Plack::Middleware::JSONP";
125             enable "Plack::Middleware::ContentLength";
126             $app;
127             };
128              
129             # and on your controller
130             $plack_request->env->{REMOTE_USER};
131             $plack_request->env->{X_OAUTH_CLIENT_ID};
132             $plack_request->env->{X_OAUTH_SCOPE};
133              
134             =head1 DESCRIPTION
135              
136             middleware for OAuth 2.0 Protected Resource endpoint
137              
138             =head1 METHODS
139              
140             =head2 call( $env )
141              
142             This method parses access token.
143             If access token is valid, authorization information are set to environment variables.
144              
145             =head1 ENV VALUES
146              
147             After successful verifying authorization within middleware layer,
148             Following 3 type of values are set in env.
149              
150             =over 4
151              
152             =item REMOTE_USER
153              
154             Identifier of user who grant the client to access the user's protected
155             resource that is stored on service provider.
156              
157             =item X_OAUTH_CLIENT
158              
159             Identifier of the client that accesses to user's protected resource
160             on beharf of the user.
161              
162             =item X_OAUTH_SCOPE
163              
164             Scope parameter that represents what kind of resources that
165             the user grant client to access.
166              
167             =back
168              
169             =head1 AUTHOR
170              
171             Lyo Kato, Elyo.kato@gmail.comE
172              
173             =head1 COPYRIGHT AND LICENSE
174              
175             Copyright (C) 2010 by Lyo Kato
176              
177             This library is free software; you can redistribute it and/or modify
178             it under the same terms as Perl itself, either Perl version 5.8.8 or,
179             at your option, any later version of Perl 5 you may have available.
180              
181             =cut
182              
183             1;