File Coverage

blib/lib/Azure/AD/ClientCredentials.pm
Criterion Covered Total %
statement 15 33 45.4
branch 0 8 0.0
condition n/a
subroutine 5 9 55.5
pod 1 1 100.0
total 21 51 41.1


line stmt bran cond sub pod time code
1             package Azure::AD::ClientCredentials;
2 1     1   1375 use Moo;
  1         11830  
  1         5  
3 1     1   2043 use Azure::AD::Errors;
  1         3  
  1         38  
4 1     1   10 use Types::Standard qw/Str Int InstanceOf/;
  1         3  
  1         12  
5 1     1   916 use JSON::MaybeXS;
  1         2  
  1         82  
6 1     1   825 use HTTP::Tiny;
  1         50713  
  1         1740  
7              
8             our $VERSION = '0.02';
9              
10             has ua_agent => (is => 'ro', isa => Str, default => sub {
11             'Azure::AD::ClientCredentials ' . $Azure::AD::ClientCredentials::VERSION
12             });
13              
14             has ua => (is => 'rw', required => 1, lazy => 1,
15             default => sub {
16             my $self = shift;
17             HTTP::Tiny->new(
18             agent => $self->ua_agent,
19             timeout => 60,
20             );
21             }
22             );
23              
24             has resource_id => (
25             is => 'ro',
26             isa => Str,
27             required => 1,
28             );
29              
30             has tenant_id => (
31             is => 'ro',
32             isa => Str,
33             required => 1,
34             default => sub {
35             $ENV{AZURE_TENANT_ID}
36             }
37             );
38              
39             has client_id => (
40             is => 'ro',
41             isa => Str,
42             required => 1,
43             default => sub {
44             $ENV{AZURE_CLIENT_ID}
45             }
46             );
47              
48             has secret_id => (
49             is => 'ro',
50             isa => Str,
51             required => 1,
52             default => sub {
53             $ENV{AZURE_SECRET_ID}
54             }
55             );
56              
57             has ad_url => (
58             is => 'ro',
59             isa => Str,
60             default => sub {
61             'https://login.microsoftonline.com'
62             },
63             );
64              
65             has token_endpoint => (
66             is => 'ro',
67             isa => Str,
68             lazy => 1,
69             default => sub {
70             my $self = shift;
71             sprintf "%s/%s/oauth2/token", $self->ad_url, $self->tenant_id;
72             }
73             );
74              
75             sub access_token {
76 0     0 1   my $self = shift;
77 0           $self->_refresh;
78 0           $self->current_creds->{ access_token };
79             }
80              
81             has current_creds => (is => 'rw');
82              
83             has expiration => (
84             is => 'rw',
85             isa => Int,
86             lazy => 1,
87             default => sub { 0 }
88             );
89              
90             sub _refresh_from_cache {
91 0     0     my $self = shift;
92             #TODO: implement caching strategy
93 0           return undef;
94             }
95              
96             sub _save_to_cache {
97 0     0     my $self = shift;
98             #TODO: implement caching strategy
99             }
100              
101             sub _refresh {
102 0     0     my $self = shift;
103              
104 0 0         if (not defined $self->current_creds) {
105 0           $self->_refresh_from_cache;
106 0 0         return $self->current_creds if (defined $self->current_creds);
107             }
108              
109 0 0         return if $self->expiration >= time;
110              
111 0           my $auth_response = $self->ua->post_form(
112             $self->token_endpoint,
113             {
114             grant_type => 'client_credentials',
115             client_id => $self->client_id,
116             client_secret => $self->secret_id,
117             resource => $self->resource_id,
118             }
119             );
120              
121 0 0         if (not $auth_response->{ success }) {
122             Azure::AD::RemoteError->throw(
123             message => $auth_response->{ content },
124             code => 'GetClientCredentialsFailed',
125             status => $auth_response->{ status }
126 0           );
127             }
128              
129 0           my $auth = decode_json($auth_response->{content});
130 0           $self->current_creds($auth);
131 0           $self->expiration($auth->{ expires_on });
132 0           $self->_save_to_cache;
133             }
134              
135             1;
136              
137             =encoding UTF-8
138              
139             =head1 NAME
140              
141             Azure::AD::ClientCredentials - Azure AD Client Credentials authentication flow
142              
143             =head1 SYNOPSIS
144              
145             use Azure::AD::ClientCredentials;
146             my $creds = Azure::AD::ClientCredentials->new(
147             resource_id => 'https://management.core.windows.net/',
148             client_id => '',
149             secret_id => '',
150             tenant_id => '',
151             );
152             say $creds->access_token;
153              
154             =head1 DESCRIPTION
155              
156             Implements the Azure AD Client Credentials flow. See L for more
157             information and alternative flows.
158              
159             =head1 ATTRIBUTES
160              
161             =head2 resource_id
162              
163             The URL for which you want a token extended (the URL of the service which you want
164             to obtain a token for).
165              
166             C for using the MS Graph API
167              
168             C for using the Azure Management APIs
169              
170             =head2 tenant_id
171              
172             The ID of the Azure Active Directory Tenant
173              
174             =head2 client_id
175              
176             The Client ID (also referred to as the Application ID) of an application
177              
178             =head2 secret_id
179              
180             A Key assigned to the Client Id.
181              
182             =head2 ad_url
183              
184             This defaults to C, and generally doesn't need to
185             be specified. Azure AD has more endpoints for some clouds:
186              
187             C China Cloud
188              
189             C US Gov Cloud
190              
191             C German Cloud
192              
193             =head1 METHODS
194              
195             =head2 access_token
196              
197             Returns the access token that has to be sent to the APIs you want to access. This
198             is normally sent in the Authentication header of HTTPS requests as a Bearer token.
199              
200             The access_token is cached in the object as long as it's valid, so subsequent calls
201             to access_token will return the appropiate token without reauthenticating to Azure AD.
202             If the token has expired, access_token will call Azure AD to obtain a new token transparently.
203              
204             Example usage:
205              
206             my $auth = Azure::AD::ClientCredentials->new(...);
207              
208             use HTTP::Tiny;
209             my $ua = HTTP::Tiny->new;
210             my $response = $ua->get(
211             'http://aservice.com/orders/list',
212             {
213             headers => { Authorization => 'Bearer ' . $auth->access_token }
214             }
215             );
216              
217             =head1 SEE ALSO
218              
219             L
220              
221             =head1 COPYRIGHT and LICENSE
222              
223             Copyright (c) 2018 by CAPSiDE
224             This code is distributed under the Apache 2 License. The full text of the
225             license can be found in the LICENSE file included with this module.
226              
227             =cut