Passed
Push — master ( 5dbaed...2ce543 )
by meta
02:51
created

AzureActiveDirectory   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 109
rs 10
c 0
b 0
f 0
wmc 11

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A buildOpenIdConfigUrl() 0 6 1
A setTenantName() 0 12 3
A checkCachedOpenIdConfig() 0 12 2
A buildAdminConsentUrl() 0 9 1
A parseOpenIdConfig() 0 6 1
A getApplicationAccessToken() 0 17 1
A downloadOpenIdConfig() 0 7 1
1
<?php
2
3
namespace Metaclassing\EnterpriseAuth;
4
5
class AzureActiveDirectory
6
{
7
    // Tenant name something.onmicrosoft.com
8
    public $tenantName = '';
9
    // Azure AD base url to use
10
    public $baseUrl = 'https://login.microsoftonline.com';
11
    // Azure AD version
12
    public $version = 'v2.0';
13
    // .well-known/openid-config
14
    public $wellKnownOpenIdConfig = '.well-known/openid-configuration';
15
    // URL to download the latest openid config
16
    public $openIdConfigUrl = '';
17
    // Contents of the openid config assoc array parsed from json
18
    public $openIdConfig = [];
19
    // AAD authorization endpoint
20
    public $authorizationEndpoint = '';
21
    // AAD token endpoint
22
    public $tokenEndpoint = '';
23
    // AAD logout endpoint
24
    public $endSessionEndpoint = '';
25
26
    public function __construct($tenantName = 'common')
27
    {
28
        $this->setTenantName($tenantName);
29
        $this->parseOpenIdConfig();
30
    }
31
32
    public function setTenantName($tenantName)
33
    {
34
        // IF we are not using the common tenant
35
        if ($tenantName != 'common') {
36
            // Make sure the tenant is formatted like xyzcorp.onmicrosoft.com
37
            $regex = '/\.onmicrosoft\.com/';
38
            if (! preg_match($regex, $tenantName, $hits)) {
39
                // Append the suffix if it is missing
40
                $tenantName .= '.onmicrosoft.com';
41
            }
42
        }
43
        $this->tenantName = $tenantName;
44
    }
45
46
    public function buildOpenIdConfigUrl()
47
    {
48
        $this->openIdConfigUrl = $this->baseUrl.'/'
49
                               . $this->tenantName.'/'
50
                               . $this->version.'/'
51
                               . $this->wellKnownOpenIdConfig;
52
    }
53
54
    public function buildAdminConsentUrl($clientId, $redirectUri)
55
    {
56
        $url = $this->baseUrl.'/'
57
             . $this->tenantName.'/'
58
             . 'adminconsent'
59
             . '?client_id='.$clientId
60
             . '&redirect_uri='.$redirectUri;
61
62
        return $url;
63
    }
64
65
    public function downloadOpenIdConfig()
66
    {
67
        $this->buildOpenIdConfigUrl();
68
        $guzzle = new \GuzzleHttp\Client();
69
        $response = $guzzle->get($this->openIdConfigUrl);
70
        $json = $response->getBody();
71
        $this->openIdConfig = json_decode($json, true);
72
    }
73
74
    public function parseOpenIdConfig()
75
    {
76
        $this->checkCachedOpenIdConfig();
77
        $this->authorizationEndpoint = $this->openIdConfig['authorization_endpoint'];
78
        $this->tokenEndpoint = $this->openIdConfig['token_endpoint'];
79
        $this->endSessionEndpoint = $this->openIdConfig['end_session_endpoint'];
80
    }
81
82
    public function checkCachedOpenIdConfig()
83
    {
84
        // See if we already have this tenants aad config cached
85
        $key = '/azureactivedirectory/'.$this->tenantName.'/config';
86
        if (\Cache::has($key)) {
87
            // Use the cached version if available
88
            $this->openIdConfig = \Cache::get($key);
89
        } else {
90
            // Download it if we dont have it
91
            $this->downloadOpenIdConfig();
92
            // Keep it around for 60 minutes
93
            \Cache::put($key, $this->openIdConfig, 60);
94
        }
95
    }
96
97
    public function getApplicationAccessToken($clientId, $clientSecret, $scopes = ['https://graph.microsoft.com/.default'])
98
    {
99
        $scope = implode(' ', $scopes);
100
        $guzzle = new \GuzzleHttp\Client();
101
        $url = $this->tokenEndpoint;
102
        $parameters = [
103
            'form_params' => [
104
                'scope'         => $scope,
105
                'grant_type'    => 'client_credentials',
106
                'client_id'     => $clientId,
107
                'client_secret' => $clientSecret,
108
            ],
109
        ];
110
        $response = $guzzle->post($url, $parameters);
111
        $responseObject = json_decode($response->getBody());
112
113
        return $responseObject->access_token;
114
    }
115
}
116