File Coverage

blib/lib/Plack/Middleware/Auth/OAuth2.pm
Criterion Covered Total %
statement 30 111 27.0
branch 0 40 0.0
condition n/a
subroutine 10 19 52.6
pod 2 2 100.0
total 42 172 24.4


line stmt bran cond sub pod time code
1             package Plack::Middleware::Auth::OAuth2;
2              
3 2     2   64792 use base qw(Plack::Middleware);
  2         8  
  2         1036  
4 2     2   25335 use strict;
  2         5  
  2         31  
5 2     2   9 use warnings;
  2         5  
  2         35  
6              
7 2     2   938 use English;
  2         8094  
  2         11  
8 2     2   1673 use Error::Pure qw(err);
  2         12630  
  2         33  
9 2     2   1397 use JSON::XS;
  2         9697  
  2         135  
10 2     2   986 use LWP::Authen::OAuth2;
  2         119836  
  2         68  
11 2     2   915 use Plack::Response;
  2         15469  
  2         60  
12 2     2   919 use Plack::Session;
  2         825  
  2         71  
13 2         8 use Plack::Util::Accessor qw(app_login app_login_url client_id client_secret
14 2     2   16 logout_path lwp_user_agent redirect_path scope service_provider);
  2         5  
15              
16             our $VERSION = 0.01;
17              
18             sub call {
19 0     0 1   my ($self, $env) = @_;
20              
21 0           my $session = Plack::Session->new($env);
22 0           my $path_info = $env->{'PATH_INFO'};
23              
24             # Check.
25 0           $self->_check_run($env);
26              
27             # Create OAuth2 object if doesn't exist.
28 0           $self->_create_oauth2_object($env);
29              
30             # Auth page.
31 0 0         if ($path_info eq '/'.$self->redirect_path) {
32 0           return $self->_app_auth_code->($env);
33             }
34              
35             # Logout page.
36 0 0         if ($path_info eq '/'.$self->logout_path) {
37 0           return $self->_app_logout->($env);
38             }
39              
40             # Check authorized.
41 0           my $authorized = $self->_authorized($env);
42              
43             # Application after authorization.
44 0 0         if ($authorized) {
45 0           return $self->app->($env);
46              
47             # Unauthorized page.
48             } else {
49 0           $self->app_login_url->($self->app_login,
50             $session->get('oauth2.obj')->authorization_url);
51 0           return $self->app_login->to_app->($env);
52             }
53             }
54              
55             sub prepare_app {
56 0     0 1   my $self = shift;
57              
58 0 0         if (! defined $self->client_id) {
59 0           err "No OAuth2 'client_id' setting.";
60             }
61              
62 0 0         if (! defined $self->client_secret) {
63 0           err "No OAuth2 'client_secret' setting.";
64             }
65              
66 0 0         if (! defined $self->app_login) {
67 0           err 'No login application.';
68             }
69              
70 0 0         if (! defined $self->app_login_url) {
71 0           err 'No login url call.';
72             }
73              
74 0 0         if (! defined $self->redirect_path) {
75 0           err 'No redirect path.';
76             }
77              
78 0 0         if (! defined $self->service_provider) {
79 0           err 'No service provider.';
80             }
81              
82 0 0         if (! defined $self->logout_path) {
83 0           $self->logout_path('logout');
84             }
85              
86 0           return;
87             }
88              
89             sub _app_auth_code {
90             return sub {
91 0     0     my $env = shift;
92              
93 0           my $req = Plack::Request->new($env);
94              
95 0           my $session = Plack::Session->new($env);
96              
97             # Process token string.
98 0           my $oauth2_code = $req->parameters->{'code'};
99 0 0         if (! defined $oauth2_code) {
100             return [
101 0           400,
102             ['Content-Type' => 'text/plain'],
103             ['No OAuth2 code.'],
104             ];
105             }
106 0           $session->get('oauth2.obj')->request_tokens('code' => $oauth2_code);
107              
108 0           my $token_string_json = $session->get('oauth2.obj')->token_string;
109 0           my $token_string_hr = JSON::XS->new->decode($token_string_json);
110 0           $session->set('oauth2.token_string', $token_string_hr);
111              
112             # Redirect.
113 0           my $res = Plack::Response->new;
114 0           $res->redirect('/');
115              
116 0           return $res->finalize;
117 0     0     };
118             }
119              
120             sub _app_logout {
121             return sub {
122 0     0     my $env = shift;
123              
124 0           my $session = Plack::Session->new($env);
125              
126             # Delete token string.
127 0 0         if (defined $session->get('oauth2.token_string')) {
128 0           $session->remove('oauth2.token_string');
129             }
130              
131             # Redirect.
132 0           my $res = Plack::Response->new;
133 0           $res->redirect('/');
134              
135 0           return $res->finalize;
136 0     0     };
137             }
138              
139             sub _authorized {
140 0     0     my ($self, $env) = @_;
141              
142 0           my $session = Plack::Session->new($env);
143              
144             # No token string.
145 0 0         if (! defined $session->get('oauth2.token_string')) {
146 0           return 0;
147             }
148              
149             # No OAuth2 object.
150 0 0         if (! defined $session->get('oauth2.obj')) {
151 0           return 0;
152             }
153              
154 0           return 1;
155             }
156              
157             sub _check_run {
158 0     0     my ($self, $env) = @_;
159              
160 0 0         if (! defined $env->{'psgix.session'}) {
161 0           err "No Plack::Middleware::Session present.";
162             }
163              
164 0           return;
165             }
166              
167             # Create OAuth2 object in session.
168             sub _create_oauth2_object {
169 0     0     my ($self, $env) = @_;
170              
171 0           my $session = Plack::Session->new($env);
172              
173             # Object is created in session.
174 0 0         if (defined $session->get('oauth2.obj')) {
175 0           return;
176             }
177              
178             # XXX Automatically https?
179 0           my $redirect_uri = 'https://'.$env->{'HTTP_HOST'};
180 0 0         if (! defined $redirect_uri) {
181 0           err 'Missing host.'
182             }
183 0           my $redirect_path = $self->redirect_path;
184 0           $redirect_uri .= '/'.$redirect_path;
185              
186             # Create object.
187 0           my $oauth2 = eval {
188 0 0         LWP::Authen::OAuth2->new(
189             'client_id' => $self->client_id,
190             'client_secret' => $self->client_secret,
191             'redirect_uri' => $redirect_uri,
192             $self->scope ? ('scope' => $self->scope) : (),
193             'service_provider' => $self->service_provider,
194             );
195             };
196 0 0         if ($EVAL_ERROR) {
197 0           err "Cannot create OAuth2 object.",
198             'Error', $EVAL_ERROR,
199             ;
200             }
201 0 0         if ($self->lwp_user_agent) {
202 0           $oauth2->set_user_agent($self->lwp_user_agent);
203             }
204 0           $session->set('oauth2.obj', $oauth2);
205              
206             # Save service provider to session.
207 0           $session->set('oauth2.service_provider', $self->service_provider);
208              
209 0           return;
210             }
211              
212             1;
213              
214             __END__