AzureActiveDirectory::parseOpenIdConfig()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
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
    // Array of RSA token signing keys indexed by KeyID
26
    public $signingKeys = [];
27
28
    public function __construct($tenantName = 'common')
29
    {
30
        $this->setTenantName($tenantName);
31
        $this->parseOpenIdConfig();
32
    }
33
34
    public function setTenantName($tenantName)
35
    {
36
        // IF we are not using the common tenant
37
        if ($tenantName != 'common') {
38
            // Make sure the tenant is formatted like xyzcorp.onmicrosoft.com
39
            $regex = '/\.onmicrosoft\.com/';
40
            if (! preg_match($regex, $tenantName, $hits)) {
41
                // Append the suffix if it is missing
42
                $tenantName .= '.onmicrosoft.com';
43
            }
44
        }
45
        $this->tenantName = $tenantName;
46
    }
47
48
    public function buildOpenIdConfigUrl()
49
    {
50
        $this->openIdConfigUrl = $this->baseUrl.'/'
51
                               .$this->tenantName.'/'
52
                               .$this->version.'/'
53
                               .$this->wellKnownOpenIdConfig;
54
    }
55
56
    public function buildAdminConsentUrl($clientId, $redirectUri)
57
    {
58
        $url = $this->baseUrl.'/'
59
             .$this->tenantName.'/'
60
             .'adminconsent'
61
             .'?client_id='.$clientId
62
             .'&redirect_uri='.$redirectUri;
63
64
        return $url;
65
    }
66
67
    public function downloadOpenIdConfig()
68
    {
69
        $this->buildOpenIdConfigUrl();
70
        $guzzle = new \GuzzleHttp\Client();
71
        $response = $guzzle->get($this->openIdConfigUrl);
72
        $json = $response->getBody();
73
        $this->openIdConfig = json_decode($json, true);
74
    }
75
76
    public function downloadSigningKeys()
77
    {
78
        $this->signingKeys = [];
79
        $guzzle = new \GuzzleHttp\Client();
80
        $response = $guzzle->get($this->openIdConfig['jwks_uri']);
81
        $json = $response->getBody();
82
        $keyData = json_decode($json, true);
83
        $keyRing = $keyData['keys'];
84
        // Loop through the keys and build us an index by kid
85
        foreach ($keyRing as $key) {
86
            $this->signingKeys[$key['kid']] = $key;
87
        }
88
    }
89
90
    public function parseOpenIdConfig()
91
    {
92
        $this->checkCachedOpenIdConfig();
93
        $this->checkCachedSigningKeys();
94
        $this->authorizationEndpoint = $this->openIdConfig['authorization_endpoint'];
95
        $this->tokenEndpoint = $this->openIdConfig['token_endpoint'];
96
        $this->endSessionEndpoint = $this->openIdConfig['end_session_endpoint'];
97
    }
98
99
    public function checkCachedOpenIdConfig()
100
    {
101
        // See if we already have this tenants aad config cached
102
        $key = '/azureactivedirectory/'.$this->tenantName.'/config';
103
        if (\Cache::has($key)) {
104
            // Use the cached version if available
105
            $this->openIdConfig = \Cache::get($key);
106
        } else {
107
            // Download it if we dont have it
108
            $this->downloadOpenIdConfig();
109
            // Keep it around for 60 minutes
110
            \Cache::put($key, $this->openIdConfig, 60);
111
        }
112
    }
113
114
    public function checkCachedSigningKeys()
115
    {
116
        // See if we already have this tenants aad config cached
117
        $key = '/azureactivedirectory/'.$this->tenantName.'/keys';
118
        if (\Cache::has($key)) {
119
            // Use the cached version if available
120
            $this->signingKeys = \Cache::get($key);
121
        } else {
122
            // Download it if we dont have it
123
            $this->downloadSigningKeys();
124
            // Keep it around for 60 minutes
125
            \Cache::put($key, $this->signingKeys, 60);
126
        }
127
    }
128
129
    public function getApplicationAccessToken($clientId, $clientSecret, $scopes = ['https://graph.microsoft.com/.default'])
130
    {
131
        $scope = implode(' ', $scopes);
132
        $guzzle = new \GuzzleHttp\Client();
133
        $url = $this->tokenEndpoint;
134
        $parameters = [
135
            'form_params' => [
136
                'scope'         => $scope,
137
                'grant_type'    => 'client_credentials',
138
                'client_id'     => $clientId,
139
                'client_secret' => $clientSecret,
140
            ],
141
        ];
142
        $response = $guzzle->post($url, $parameters);
143
        $responseObject = json_decode($response->getBody());
144
145
        return $responseObject->access_token;
146
    }
147
}
148