File Coverage

blib/lib/Net/OAuth2/AuthorizationServer/ImplicitGrant.pm
Criterion Covered Total %
statement 46 49 93.8
branch 20 22 90.9
condition 10 13 76.9
subroutine 9 10 90.0
pod 0 1 0.0
total 85 95 89.4


line stmt bran cond sub pod time code
1             package Net::OAuth2::AuthorizationServer::ImplicitGrant;
2              
3             =head1 NAME
4              
5             Net::OAuth2::AuthorizationServer::ImplicitGrant - OAuth2 Resource Owner Implicit Grant
6              
7             You "SHOULD NOT" use this grant type (see L)
8              
9             =head1 SYNOPSIS
10              
11             my $Grant = Net::OAuth2::AuthorizationServer::ImplicitGrant->new(
12             clients => {
13             TrendyNewService => {
14             # optional
15             redirect_uri => 'https://...',
16             # optional
17             scopes => {
18             post_images => 1,
19             annoy_friends => 1,
20             },
21             },
22             }
23             );
24              
25             # verify a client against known clients
26             my ( $is_valid,$error,$scopes ) = $Grant->verify_client(
27             client_id => $client_id,
28             redirect_uri => $uri, # optional
29             scopes => [ qw/ list of scopes / ], # optional
30             );
31              
32             if ( ! $Grant->login_resource_owner ) {
33             # resource owner needs to login
34             ...
35             }
36              
37             # have resource owner confirm (and perhaps modify) scopes
38             my ( $confirmed,$error,$scopes_ref ) = $Grant->confirm_by_resource_owner(
39             client_id => $client_id,
40             scopes => [ qw/ list of scopes / ],
41             );
42              
43             # generate a token
44             my $token = $Grant->token(
45             client_id => $client_id,
46             scopes => $scopes_ref,
47             redirect_uri => $redirect_uri,
48             user_id => $user_id, # optional
49             jwt_claims_cb => sub { ... }, # optional, see jwt_claims_cb in Manual
50             );
51              
52             # store access token
53             $Grant->store_access_token(
54             client_id => $client,
55             access_token => $access_token,
56             scopes => $scopes_ref,
57             );
58              
59             # verify an access token
60             my ( $is_valid,$error ) = $Grant->verify_access_token(
61             access_token => $access_token,
62             scopes => $scopes_ref,
63             );
64              
65             =head1 DESCRIPTION
66              
67             This module implements the OAuth2 "Resource Owner Implicit Grant" flow as described
68             at L.
69              
70             =head1 CONSTRUCTOR ARGUMENTS
71              
72             Along with those detailed at L
73             the following are supported by this grant type:
74              
75             =head1 CALLBACK FUNCTIONS
76              
77             The following callbacks are supported by this grant type:
78              
79             verify_client_cb
80             login_resource_owner_cb
81             confirm_by_resource_owner_cb
82             store_access_token_cb
83             verify_access_token_cb
84              
85             Please see L for
86             documentation on each callback function.
87              
88             =cut
89              
90 5     5   3223 use strict;
  5         15  
  5         171  
91 5     5   29 use warnings;
  5         12  
  5         156  
92              
93 5     5   1100 use Moo;
  5         24795  
  5         32  
94             with 'Net::OAuth2::AuthorizationServer::Defaults';
95              
96 5     5   4469 use Carp qw/ croak /;
  5         13  
  5         324  
97 5     5   1184 use Types::Standard qw/ :all /;
  5         160584  
  5         64  
98              
99 6     6   44 sub _uses_auth_codes { 0 };
100 0     0   0 sub _uses_user_passwords { 0 };
101              
102             sub BUILD {
103 12     12 0 549 my ( $self, $args ) = @_;
104              
105 12 100 66     68 if (
106             # if we don't have a list of clients
107             !$self->_has_clients
108              
109             # we must know how to verify clients and tokens
110             and ( !$args->{ verify_client_cb }
111             and !$args->{ store_access_token_cb }
112             and !$args->{ verify_access_token_cb } )
113             )
114             {
115 2         36 croak __PACKAGE__ . " requires either clients or overrides";
116             }
117             }
118              
119             sub _verify_client {
120 32     32   150 my ( $self, %args ) = @_;
121              
122             my ( $client_id, $scopes_ref, $redirect_uri )
123 32         91 = @args{ qw/ client_id scopes redirect_uri / };
124              
125 32 100       127 if ( my $client = $self->clients->{ $client_id } ) {
126 28         60 my $client_scopes = [];
127              
128 28   50     49 foreach my $scope ( @{ $scopes_ref // [] } ) {
  28         91  
129 64 100       250 if ( ! exists($self->clients->{ $client_id }{ scopes }{ $scope }) ) {
    100          
130 4         28 return ( 0, 'invalid_scope' );
131             }
132             elsif ( $self->clients->{ $client_id }{ scopes }{ $scope } ) {
133 56         93 push @{$client_scopes}, $scope;
  56         132  
134             }
135             }
136            
137 24 100 100     133 if (
      100        
138             # redirect_uri is optional
139             $self->clients->{ $client_id }{ redirect_uri }
140             && (
141             ! $redirect_uri
142             || $redirect_uri ne $self->clients->{ $client_id }{ redirect_uri }
143             )
144             ) {
145 8         55 return ( 0, 'invalid_request' );
146             }
147              
148 16 100       49 if (
149             # implies Authorization Code Grant, not Implicit Grant
150             $self->clients->{ $client_id }{ client_secret }
151             ) {
152 4         32 return ( 0, 'unauthorized_client' );
153             }
154              
155 12         75 return ( 1, undef, $client_scopes );
156             }
157              
158 4         26 return ( 0, 'unauthorized_client' );
159             }
160              
161             sub _verify_access_token {
162 40     40   154 my ( $self, %args ) = @_;
163              
164 40         88 delete( $args{is_refresh_token} ); # not supported by implicit grant
165              
166 40 100       186 return $self->_verify_access_token_jwt( %args ) if $self->jwt_secret;
167              
168             my ( $a_token, $scopes_ref ) =
169 20         54 @args{ qw/ access_token scopes / };
170              
171 20 100       65 if ( exists( $self->access_tokens->{ $a_token } ) ) {
172              
173 12 50       56 if ( $self->access_tokens->{ $a_token }{ expires } <= time ) {
    50          
174 0         0 $self->_revoke_access_token( $a_token );
175 0         0 return ( 0, 'invalid_grant' );
176             }
177             elsif ( $scopes_ref ) {
178              
179 12   50     20 foreach my $scope ( @{ $scopes_ref // [] } ) {
  12         38  
180             return ( 0, 'invalid_grant' )
181 20 100       71 if !$self->_has_scope( $scope, $self->access_tokens->{ $a_token }{ scope } );
182             }
183              
184             }
185              
186 8         76 return ( $self->access_tokens->{ $a_token }{ client_id }, undef );
187             }
188              
189 8         48 return ( 0, 'invalid_grant' );
190             }
191              
192             =head1 AUTHOR
193              
194             Lee Johnson - C
195              
196             =head1 LICENSE
197              
198             This library is free software; you can redistribute it and/or modify it under
199             the same terms as Perl itself. If you would like to contribute documentation
200             or file a bug report then please raise an issue / pull request:
201              
202             https://github.com/Humanstate/net-oauth2-authorizationserver
203              
204             =cut
205              
206             __PACKAGE__->meta->make_immutable;