diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -99,6 +99,7 @@ 'PhutilAuthCredentialException' => 'auth/exception/PhutilAuthCredentialException.php', 'PhutilAuthException' => 'auth/exception/PhutilAuthException.php', 'PhutilAuthUserAbortedException' => 'auth/exception/PhutilAuthUserAbortedException.php', + 'PhutilAzureAuthAdapter' => 'auth/PhutilAzureAuthAdapter.php', 'PhutilBallOfPHP' => 'phage/util/PhutilBallOfPHP.php', 'PhutilBitbucketAuthAdapter' => 'auth/PhutilBitbucketAuthAdapter.php', 'PhutilBootloader' => 'moduleutils/PhutilBootloader.php', @@ -544,6 +545,7 @@ 'PhutilAuthCredentialException' => 'PhutilAuthException', 'PhutilAuthException' => 'Exception', 'PhutilAuthUserAbortedException' => 'PhutilAuthException', + 'PhutilAzureAuthAdapter' => 'PhutilOAuthAuthAdapter', 'PhutilBitbucketAuthAdapter' => 'PhutilOAuth1AuthAdapter', 'PhutilBootloaderException' => 'Exception', 'PhutilBufferedIterator' => 'Iterator', diff --git a/src/auth/PhutilAzureAuthAdapter.php b/src/auth/PhutilAzureAuthAdapter.php new file mode 100644 --- /dev/null +++ b/src/auth/PhutilAzureAuthAdapter.php @@ -0,0 +1,66 @@ + 'code'); + } + + public function getExtraTokenParameters() { + return array('resource' => 'https://graph.windows.net', + 'grant_type' => 'authorization_code'); + } + + public function getAccountID() { + return $this->getOAuthAccountData('oid'); + } + + public function getAccountEmail() { + return $this->getOAuthAccountData('upn'); + } + + public function getAccountName() { + return $this->getOAuthAccountData('unique_name'); + } + + public function getAccountRealName() { + return $this->getOAuthAccountData('given_name').' '.$this->getOAuthAccountData('family_name'); + } + + protected function getAuthenticateBaseURI() { + return 'https://login.windows.net/common/oauth2/authorize'; + } + + protected function getTokenBaseURI() { + return 'https://login.windows.net/common/oauth2/token'; + } + + private function decodeJWTComponent($component) { + return json_decode(base64_decode(urldecode($component)), true); + } + + protected function loadOAuthAccountData() { + $jwt_token = $this->getAccessTokenData('id_token'); + $token_parts = explode('.', $jwt_token); + + $header = $this->decodeJWTComponent($token_parts[0]); + $body = $this->decodeJWTComponent($token_parts[1]); + + if (!is_array($header) || !is_array($body)) { + throw new Exception( + 'Expected valid JWT response from Azure token service, '. + 'got: '.$jwt_token); + } + + return $body; + } + +}