Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
96.15% |
25 / 26 |
|
85.71% |
6 / 7 |
CRAP | |
0.00% |
0 / 1 |
Microsoft | |
96.15% |
25 / 26 |
|
85.71% |
6 / 7 |
11 | |
0.00% |
0 / 1 |
getAuthorizeUrl | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getAccessTokenUrl | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getScope | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__construct | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
getUserProfile | |
100.00% |
18 / 18 |
|
100.00% |
1 / 1 |
4 | |||
getLogoSource | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getThemeColor | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Miniframe\SocialLogin\Provider; |
4 | |
5 | use Miniframe\Core\Config; |
6 | use Miniframe\Core\Request; |
7 | use Miniframe\SocialLogin\Model\User; |
8 | |
9 | class Microsoft extends AbstractOAuth2Provider |
10 | { |
11 | /** |
12 | * Returns the Authorize URL |
13 | * |
14 | * @return string |
15 | */ |
16 | protected function getAuthorizeUrl(): string |
17 | { |
18 | return 'https://login.microsoftonline.com/' . $this->tenant . '/oauth2/v2.0/authorize'; |
19 | } |
20 | |
21 | /** |
22 | * Returns the Access Token URL |
23 | * |
24 | * @return string |
25 | */ |
26 | protected function getAccessTokenUrl(): string |
27 | { |
28 | return 'https://login.microsoftonline.com/' . $this->tenant . '/oauth2/v2.0/token'; |
29 | } |
30 | |
31 | /** |
32 | * The tenant ID. Valid values are common, organizations, consumers, and tenant identifiers. |
33 | * |
34 | * @var string |
35 | * |
36 | * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow |
37 | */ |
38 | protected $tenant = 'common'; |
39 | |
40 | /** |
41 | * Returns the requested scope |
42 | * |
43 | * @return string|null |
44 | */ |
45 | protected function getScope(): ?string |
46 | { |
47 | return 'User.Read'; |
48 | } |
49 | |
50 | /** |
51 | * Creates a new Microsoft OAuth 2.0 provider |
52 | * |
53 | * @param Request $request Reference to the Request object. |
54 | * @param Config $config Reference to the Config object. |
55 | */ |
56 | public function __construct(Request $request, Config $config) |
57 | { |
58 | parent::__construct($request, $config); |
59 | if ($config->has('sociallogin-microsoft', 'tenant')) { |
60 | $this->tenant = $config->get('sociallogin-microsoft', 'tenant'); |
61 | } |
62 | } |
63 | |
64 | /** |
65 | * Returns the user profile |
66 | * |
67 | * @param array $accessToken The access token. |
68 | * |
69 | * @return User |
70 | */ |
71 | protected function getUserProfile(array $accessToken): User |
72 | { |
73 | $userData = $this->curlRequest('https://graph.microsoft.com/v1.0/me', 'GET', [], [ |
74 | 'Authorization: Bearer ' . $accessToken['access_token'], |
75 | ]); |
76 | |
77 | // When fetching the avatar fails, fall back to Gravatar |
78 | $avatar = 'https://s.gravatar.com/avatar/' . md5(strtolower(trim($userData['userPrincipalName']))) |
79 | . '?s=80&d=identicon'; |
80 | |
81 | foreach ( |
82 | [ |
83 | // For business accounts (Office 365), the avatar can be located here: |
84 | 'https://graph.microsoft.com/v1.0/me/photo/$value', |
85 | // For personal accounts (Hotmail, etc.), the avatar can be located here: |
86 | 'https://graph.microsoft.com/beta/me/photo/$value' |
87 | ] as $url |
88 | ) { |
89 | try { |
90 | $avatarBlob = $this->curlRequest($url, 'GET', [], [ |
91 | 'Authorization: Bearer ' . $accessToken['access_token'], |
92 | ], true); |
93 | $avatar = 'data:' . $avatarBlob['contentType'] . ';base64,' |
94 | . base64_encode($avatarBlob['responseBody']); |
95 | break; |
96 | } catch (\RuntimeException $exception) { |
97 | if ($exception->getMessage() == 'HTTP #404 error') { |
98 | continue; |
99 | } |
100 | throw $exception; |
101 | } |
102 | } |
103 | |
104 | return new User( |
105 | $userData['id'], |
106 | $userData['userPrincipalName'], |
107 | $userData['displayName'], |
108 | $avatar, |
109 | static::class, |
110 | ['accessToken' => $accessToken, 'userData' => $userData] |
111 | ); |
112 | } |
113 | |
114 | /** |
115 | * Returns the image source for the logo of this provider. |
116 | * |
117 | * @return string |
118 | */ |
119 | public static function getLogoSource(): string |
120 | { |
121 | return 'data:image/svg+xml;base64,' |
122 | . base64_encode(file_get_contents(__DIR__ . '/../../templates/logos/Microsoft.svg')); |
123 | } |
124 | |
125 | /** |
126 | * Returns the theme color for this provider. |
127 | * |
128 | * @return string |
129 | */ |
130 | public static function getThemeColor(): string |
131 | { |
132 | return 'rgb(0, 103, 184)'; |
133 | } |
134 | } |