File Coverage

blib/lib/Twitter/API/Trait/AppAuth.pm
Criterion Covered Total %
statement 22 22 100.0
branch 4 4 100.0
condition n/a
subroutine 7 7 100.0
pod 2 3 66.6
total 35 36 97.2


line stmt bran cond sub pod time code
1             package Twitter::API::Trait::AppAuth;
2             # ABSTRACT: App-only (OAuth2) Authentication
3             $Twitter::API::Trait::AppAuth::VERSION = '1.0006';
4 3     3   1859 use Moo::Role;
  3         8  
  3         23  
5 3     3   986 use Carp;
  3         5  
  3         187  
6 3     3   17 use URL::Encode qw/url_encode url_decode/;
  3         21  
  3         152  
7 3     3   18 use namespace::clean;
  3         6  
  3         20  
8              
9             requires qw/
10             _url_for access_token add_authorization api_url consumer_key
11             consumer_secret request
12             /;
13              
14             # private methods
15              
16             sub oauth2_url_for {
17 6     6 0 14 my $self = shift;
18              
19 6         50 $self->_url_for('', $self->api_url, 'oauth2', @_);
20             }
21              
22             my $add_consumer_auth_header = sub {
23             my ( $self, $req ) = @_;
24              
25             $req->headers->authorization_basic(
26             $self->consumer_key, $self->consumer_secret);
27             };
28              
29             # public methods
30              
31             #pod =method oauth2_token
32             #pod
33             #pod Call the C<oauth2/token> endpoint to get a bearer token. The token is not
34             #pod stored in Twitter::API's state. If you want that, set the C<access_token>
35             #pod attribute with the returned token.
36             #pod
37             #pod See L<https://developer.twitter.com/en/docs/basics/authentication/api-reference/token> for details.
38             #pod
39             #pod =cut
40              
41             sub oauth2_token {
42 3     3 1 1164 my $self = shift;
43              
44 3         27 my ( $r, $c ) = $self->request(post => $self->oauth2_url_for('token'), {
45             -add_consumer_auth_header => 1,
46             grant_type => 'client_credentials',
47             });
48              
49             # In their wisdom, Twitter sends us a URL encoded token. We need to decode
50             # it, so if/when we call invalidate_token, and properly URL encode our
51             # parameters, we don't end up with a double-encoded token.
52 3         16 my $token = url_decode $$r{access_token};
53 3 100       80 return wantarray ? ( $token, $c ) : $token;
54             }
55              
56             #pod =method invalidate_token($token)
57             #pod
58             #pod Calls the C<oauth2/invalidate_token> endpoint to revoke a token. See
59             #pod L<https://developer.twitter.com/en/docs/basics/authentication/api-reference/invalidate_token> for
60             #pod details.
61             #pod
62             #pod =cut
63              
64             sub invalidate_token {
65 2     2 1 836 my ( $self, $token ) = @_;
66              
67 2         6 my ( $r, $c ) = $self->request(
68             post =>$self->oauth2_url_for('invalidate_token'), {
69             -add_consumer_auth_header => 1,
70             access_token => $token,
71             });
72 2         7 my $token_returned = url_decode $$r{access_token};
73 2 100       41 return wantarray ? ( $token_returned, $c ) : $token_returned;
74             }
75              
76             # request chain modifiers
77              
78             around add_authorization => sub {
79             shift; # we're overriding the base, so we won't call it
80             my ( $self, $c ) = @_;
81              
82             my $req = $c->http_request;
83             if ( $c->get_option('add_consumer_auth_header') ) {
84             $self->$add_consumer_auth_header($req);
85             }
86             else {
87             my $token = $c->get_option('token') // $self->access_token // return;
88             $req->header(authorization => join ' ', Bearer => url_encode($token));
89             }
90             };
91              
92             1;
93              
94             __END__
95              
96             =pod
97              
98             =encoding UTF-8
99              
100             =head1 NAME
101              
102             Twitter::API::Trait::AppAuth - App-only (OAuth2) Authentication
103              
104             =head1 VERSION
105              
106             version 1.0006
107              
108             =head1 SYNOPSIS
109              
110             use Twitter::API;
111             my $client = Twitter::API->new_with_traits(
112             traits => [ qw/ApiMethods AppAuth/ ]);
113              
114             my $r = $client->oauth2_token;
115             # return value is hash ref:
116             # { token_type => 'bearer', access_token => 'AA...' }
117             my $token = $r->{access_token};
118              
119             # you can use the token explicitly with the -token argument:
120             my $user = $client->show_user('twitter_api', { -token => $token });
121              
122             # or you can set the access_token attribute to use it implicitly
123             $client->access_token($token);
124             my $user = $client->show_user('twitterapi');
125              
126             # to revoke a token
127             $client->invalidate_token($token);
128              
129             # if you revoke the token stored in the access_token attribute, clear it:
130             $client->clear_access_token;
131              
132             =head1 METHODS
133              
134             =head2 oauth2_token
135              
136             Call the C<oauth2/token> endpoint to get a bearer token. The token is not
137             stored in Twitter::API's state. If you want that, set the C<access_token>
138             attribute with the returned token.
139              
140             See L<https://developer.twitter.com/en/docs/basics/authentication/api-reference/token> for details.
141              
142             =head2 invalidate_token($token)
143              
144             Calls the C<oauth2/invalidate_token> endpoint to revoke a token. See
145             L<https://developer.twitter.com/en/docs/basics/authentication/api-reference/invalidate_token> for
146             details.
147              
148             =head1 AUTHOR
149              
150             Marc Mims <marc@questright.com>
151              
152             =head1 COPYRIGHT AND LICENSE
153              
154             This software is copyright (c) 2015-2021 by Marc Mims.
155              
156             This is free software; you can redistribute it and/or modify it under
157             the same terms as the Perl 5 programming language system itself.
158              
159             =cut