{"id":17800409,"url":"https://github.com/thenetworg/oauth2-azure","last_synced_at":"2025-10-05T12:59:55.679Z","repository":{"id":37743125,"uuid":"46269984","full_name":"TheNetworg/oauth2-azure","owner":"TheNetworg","description":"Azure AD provider for the OAuth 2.0 Client.","archived":false,"fork":false,"pushed_at":"2025-03-05T08:12:05.000Z","size":198,"stargazers_count":240,"open_issues_count":68,"forks_count":114,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-22T17:14:54.241Z","etag":null,"topics":["aad","aad-b2c","azure","azure-active-directory","microsoft","microsoft-graph","php"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/thenetworg/oauth2-azure","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TheNetworg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-11-16T11:15:47.000Z","updated_at":"2025-05-17T06:42:13.000Z","dependencies_parsed_at":"2024-05-06T22:24:25.136Z","dependency_job_id":"c5177187-ae2e-4b64-8740-e7830bcf90c8","html_url":"https://github.com/TheNetworg/oauth2-azure","commit_stats":{"total_commits":107,"total_committers":28,"mean_commits":"3.8214285714285716","dds":0.485981308411215,"last_synced_commit":"dc095e5a6ae485be8a0c8b88a0d07616c18d484b"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/TheNetworg/oauth2-azure","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNetworg%2Foauth2-azure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNetworg%2Foauth2-azure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNetworg%2Foauth2-azure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNetworg%2Foauth2-azure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheNetworg","download_url":"https://codeload.github.com/TheNetworg/oauth2-azure/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNetworg%2Foauth2-azure/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278457468,"owners_count":25989956,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aad","aad-b2c","azure","azure-active-directory","microsoft","microsoft-graph","php"],"created_at":"2024-10-27T12:21:28.126Z","updated_at":"2025-10-05T12:59:55.662Z","avatar_url":"https://github.com/TheNetworg.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Azure Active Directory Provider for OAuth 2.0 Client\n[![Latest Version](https://img.shields.io/github/release/thenetworg/oauth2-azure.svg?style=flat-square)](https://github.com/thenetworg/oauth2-azure/releases)\n[![Total Downloads](https://img.shields.io/packagist/dt/thenetworg/oauth2-azure.svg?style=flat-square)](https://packagist.org/packages/thenetworg/oauth2-azure)\n[![Software License](https://img.shields.io/packagist/l/thenetworg/oauth2-azure.svg?style=flat-square)](LICENSE.md)\n\nThis package provides [Azure Active Directory](https://azure.microsoft.com/en-us/services/active-directory/) OAuth 2.0 support for the PHP League's [OAuth 2.0 Client](https://github.com/thephpleague/oauth2-client).\n\n## Table of Contents\n- [Installation](#installation)\n- [Usage](#usage)\n    - [Authorization Code Flow](#authorization-code-flow)\n        - [Advanced flow](#advanced-flow)\n        - [Using custom parameters](#using-custom-parameters)\n        - [**NEW** - Call on behalf of a token provided by another app](#call-on-behalf-of-a-token-provided-by-another-app)\n    - [**NEW** - Logging out](#logging-out)\n- [Making API Requests](#making-api-requests)\n    - [Variables](#variables)\n- [Resource Owner](#resource-owner)\n- [**UPDATED** - Microsoft Graph](#microsoft-graph)\n- [**NEW** - Protecting your API - *experimental*](#protecting-your-api---experimental)\n- [Azure Active Directory B2C - *experimental*](#azure-active-directory-b2c---experimental)\n- [Multipurpose refresh tokens - *experimental*](#multipurpose-refresh-tokens---experimental)\n- [Known users](#known-users)\n- [Contributing](#contributing)\n- [Credits](#credits)\n- [Support](#support)\n- [License](#license)\n\n## Installation\n\nTo install, use composer:\n\n```\ncomposer require thenetworg/oauth2-azure\n```\n\n## Usage\n\nUsage is the same as The League's OAuth client, using `\\TheNetworg\\OAuth2\\Client\\Provider\\Azure` as the provider.\n\n### Authorization Code Flow\n\n```php\n$provider = new TheNetworg\\OAuth2\\Client\\Provider\\Azure([\n    'clientId'          =\u003e '{azure-client-id}',\n    'clientSecret'      =\u003e '{azure-client-secret}',\n    'redirectUri'       =\u003e 'https://example.com/callback-url',\n    //Optional using key pair instead of secret\n    'clientCertificatePrivateKey' =\u003e '{azure-client-certificate-private-key}',\n    //Optional using key pair instead of secret\n    'clientCertificateThumbprint' =\u003e '{azure-client-certificate-thumbprint}',\n    //Optional\n    'scopes'            =\u003e ['openid'],\n    //Optional\n    'defaultEndPointVersion' =\u003e '2.0'\n]);\n\n// Set to use v2 API, skip the line or set the value to Azure::ENDPOINT_VERSION_1_0 if willing to use v1 API\n$provider-\u003edefaultEndPointVersion = TheNetworg\\OAuth2\\Client\\Provider\\Azure::ENDPOINT_VERSION_2_0;\n\n$baseGraphUri = $provider-\u003egetRootMicrosoftGraphUri(null);\n$provider-\u003escope = 'openid profile email offline_access ' . $baseGraphUri . '/User.Read';\n\nif (isset($_GET['code']) \u0026\u0026 isset($_SESSION['OAuth2.state']) \u0026\u0026 isset($_GET['state'])) {\n    if ($_GET['state'] == $_SESSION['OAuth2.state']) {\n        unset($_SESSION['OAuth2.state']);\n\n        // Try to get an access token (using the authorization code grant)\n        /** @var AccessToken $token */\n        $token = $provider-\u003egetAccessToken('authorization_code', [\n            'scope' =\u003e $provider-\u003escope,\n            'code' =\u003e $_GET['code'],\n        ]);\n\n        // Verify token\n        // Save it to local server session data\n        \n        return $token-\u003egetToken();\n    } else {\n        echo 'Invalid state';\n\n        return null;\n    }\n} else {\n    // // Check local server's session data for a token\n    // // and verify if still valid \n    // /** @var ?AccessToken $token */\n    // $token = // token cached in session data, null if not found;\n    //\n    // if (isset($token)) {\n    //    $me = $provider-\u003eget($provider-\u003egetRootMicrosoftGraphUri($token) . '/v1.0/me', $token);\n    //    $userEmail = $me['mail'];\n    //\n    //    if ($token-\u003ehasExpired()) {\n    //        if (!is_null($token-\u003egetRefreshToken())) {\n    //            $token = $provider-\u003egetAccessToken('refresh_token', [\n    //                'scope' =\u003e $provider-\u003escope,\n    //                'refresh_token' =\u003e $token-\u003egetRefreshToken()\n    //            ]);\n    //        } else {\n    //            $token = null;\n    //        }\n    //    }\n    //}\n    //\n    // If the token is not found in \n    // if (!isset($token)) {\n        $authorizationUrl = $provider-\u003egetAuthorizationUrl(['scope' =\u003e $provider-\u003escope]);\n\n        $_SESSION['OAuth2.state'] = $provider-\u003egetState();\n\n        header('Location: ' . $authorizationUrl);\n\n        exit;\n    // }\n\n    return $token-\u003egetToken();\n}\n```\n\n#### Advanced flow\n\nThe [Authorization Code Grant Flow](https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx) is a little bit different for Azure Active Directory. Instead of scopes, you specify the resource which you would like to access - there is a param `$provider-\u003eauthWithResource` which will automatically populate the `resource` param of request with the value of either `$provider-\u003eresource` or `$provider-\u003eurlAPI`. This feature is mostly intended for v2.0 endpoint of Azure AD (see more [here](https://docs.microsoft.com/en-us/azure/active-directory/develop/azure-ad-endpoint-comparison#scopes-not-resources)).\n\n#### Using custom parameters\n\nWith [oauth2-client](https://github.com/thephpleague/oauth2-client) of version 1.3.0 and higher, it is now possible to specify custom parameters for the authorization URL, so you can now make use of options like `prompt`, `login_hint` and similar. See the following example of obtaining an authorization URL which will force the user to reauthenticate:\n```php\n$authUrl = $provider-\u003egetAuthorizationUrl([\n    'prompt' =\u003e 'login'\n]);\n```\nYou can find additional parameters [here](https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx).\n\n#### Using a certificate key pair instead of the shared secret\n\n- Generate a key pair, e.g. with:\n```bash\nopenssl genrsa -out private.key 2048\nopenssl req -new -x509 -key private.key -out publickey.cer -days 365\n```\n- Upload the `publickey.cer` to your app in the Azure portal\n- Note the displayed thumbprint for the certificate (it looks like `B4A94A83092455AC4D3AC827F02B61646EAAC43D`)\n- Put that thumbprint into the `clientCertificateThumbprint` constructor option\n- Put the contents of `private.key` into the `clientCertificatePrivateKey` constructor option\n- You can omit the `clientSecret` constructor option\n\n### Logging out\nIf you need to quickly generate a logout URL for the user, you can do following:\n```php\n// Assuming you have provider properly initialized.\n$post_logout_redirect_uri = 'https://www.msn.com'; // The logout destination after the user is logged out from their account.\n$logoutUrl = $provider-\u003egetLogoutUrl($post_logout_redirect_uri);\nheader('Location: '.$logoutUrl); // Redirect the user to the generated URL\n```\n\n#### Call on behalf of a token provided by another app\n\n```php\n// Use token provided by the other app\n// Make sure the other app mentioned this app in the scope when requesting the token\n$suppliedToken = '';  \n\n$provider = xxxxx;// Initialize provider\n\n// Call this to get claims\n// $claims = $provider-\u003evalidateAccessToken($suppliedToken);\n\n/** @var AccessToken $token */\n$token = $provider-\u003egetAccessToken('jwt_bearer', [\n    'scope' =\u003e $provider-\u003escope,\n    'assertion' =\u003e $suppliedToken,\n    'requested_token_use' =\u003e 'on_behalf_of',\n]);\n```\n\n## Making API Requests\n\nThis library also provides easy interface to make it easier to interact with [Azure Graph API](https://msdn.microsoft.com/en-us/library/azure/hh974476.aspx) and [Microsoft Graph](http://graph.microsoft.io), the following methods are available on `provider` object (it also handles automatic token refresh flow should it be needed during making the request):\n\n- `get($ref, $accessToken, $headers = [])`\n- `post($ref, $body, $accessToken, $headers = [])`\n- `put($ref, $body, $accessToken, $headers = [])`\n- `delete($ref, $body, $accessToken, $headers = [])`\n- `patch($ref, $body, $accessToken, $headers = [])`\n- `getObjects($tenant, $ref, $accessToken, $headers = [])` This is used for example for listing large amount of data - where you need to list all users for example - it automatically follows `odata.nextLink` until the end.\n  - `$tenant` tenant has to be provided since the `odata.nextLink` doesn't contain it.\n- `request($method, $ref, $accessToken, $options = [])` See [#36](https://github.com/TheNetworg/oauth2-azure/issues/36) for use case.\n\n*Please note that if you need to create a custom request, the method getAuthenticatedRequest and getResponse can still be used.*\n\n### Variables\n- `$ref` The URL reference without the leading `/`, for example `myOrganization/groups`\n- `$body` The contents of the request, make has to be either string (so make sure to use `json_encode` to encode the request)s or stream (see [Guzzle HTTP](http://docs.guzzlephp.org/en/latest/request-options.html#body))\n- `$accessToken` The access token object obtained by using `getAccessToken` method\n- `$headers` Ability to set custom headers for the request (see [Guzzle HTTP](http://docs.guzzlephp.org/en/latest/request-options.html#headers))\n\n## Resource Owner\nWith version 1.1.0 and onward, the Resource Owner information is parsed from the JWT passed in `access_token` by Azure Active Directory. It exposes few attributes and one function.\n\n**Example:**\n```php\n$resourceOwner = $provider-\u003egetResourceOwner($token);\necho 'Hello, '.$resourceOwner-\u003egetFirstName().'!';\n```\nThe exposed attributes and function are:\n- `getId()` - Gets user's object id - unique for each user\n- `getFirstName()` - Gets user's first name\n- `getLastName()` - Gets user's family name/surname\n- `getTenantId()` - Gets id of tenant which the user is member of\n- `getUpn()` - Gets user's User Principal Name, which can be also used as user's e-mail address\n- `claim($name)` - Gets any other claim (specified as `$name`) from the JWT, full list can be found [here](https://azure.microsoft.com/en-us/documentation/articles/active-directory-token-and-claims/)\n\n## Microsoft Graph\nCalling [Microsoft Graph](http://graph.microsoft.io/) is very simple with this library. After provider initialization simply change the API URL followingly (replace `v1.0` with your desired version):\n```php\n// Mention Microsoft Graph scope when initializing the provider \n$baseGraphUri = $provider-\u003egetRootMicrosoftGraphUri(null);\n$provider-\u003escope = 'your scope ' . $baseGraphUri . '/User.Read';\n\n// Call a query\n$provider-\u003eget($provider-\u003egetRootMicrosoftGraphUri($token) . '/v1.0/me', $token);\n```\nAfter that, when requesting access token, refresh token or so, provide the `resource` with value `https://graph.microsoft.com/` in order to be able to make calls to the Graph (see more about `resource` [here](#advanced-flow)).\n\n## Protecting your API - *experimental*\nWith version 1.2.0 you can now use this library to protect your API with Azure Active Directory authentication very easily. The Provider now also exposes `validateAccessToken(string $token)` which lets you pass an access token inside which you for example received in the `Authorization` header of the request on your API. You can use the function followingly (in vanilla PHP):\n```php\n// Assuming you have already initialized the $provider\n\n// Obtain the accessToken - in this case, we are getting it from Authorization header.\n// If you're instead using a persisted access token you got from $provider-\u003egetAccessToken,\n// you'll have to feed its id token to validateAccessToken like so: $provider-\u003evalidateAccessToken($accessTokenn-\u003egetIdToken());\n$headers = getallheaders();\n// Assuming you got the value of Authorization header as \"Bearer [the_access_token]\" we parse it\n$authorization = explode(' ', $headers['Authorization']);\n$accessToken = $authorization[1];\n\ntry {\n    $claims = $provider-\u003evalidateAccessToken($accessToken);\n} catch (Exception $e) {\n    // Something happened, handle the error\n}\n\n// The access token is valid, you can now proceed with your code. You can also access the $claims as defined in JWT - for example roles, group memberships etc.\n```\n\nYou may also need to access some other resource from the API like the Microsoft Graph to get some additional information. In order to do that, there is `urn:ietf:params:oauth:grant-type:jwt-bearer` grant available ([RFC](https://tools.ietf.org/html/draft-jones-oauth-jwt-bearer-03)). An example (assuming you have the code above working and you have the required permissions configured correctly in the Azure AD application):\n```php\n$graphAccessToken = $provider-\u003egetAccessToken('jwt_bearer', [\n    'resource' =\u003e 'https://graph.microsoft.com/v1.0/',\n    'assertion' =\u003e $accessToken,\n    'requested_token_use' =\u003e 'on_behalf_of'\n]);\n\n$me = $provider-\u003eget('https://graph.microsoft.com/v1.0/me', $graphAccessToken);\nprint_r($me);\n```\nJust to make it easier so you don't have to remember entire name for `grant_type` (`urn:ietf:params:oauth:grant-type:jwt-bearer`), you just use short `jwt_bearer` instead.\n\n## Azure Active Directory B2C - *experimental*\nYou can also now very simply make use of [Azure Active Directory B2C](https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-reference-oauth-code/). Before authentication, change the endpoints using `pathAuthorize`, `pathToken` and `scope` and additionally specify your [login policy](https://azure.microsoft.com/en-gb/documentation/articles/active-directory-b2c-reference-policies/). **Please note that the B2C support is still experimental and wasn't fully tested.**\n```php\n$provider-\u003epathAuthorize = \"/oauth2/v2.0/authorize\";\n$provider-\u003epathToken = \"/oauth2/v2.0/token\";\n$provider-\u003escope = [\"idtoken\"];\n\n// Specify custom policy in our authorization URL\n$authUrl = $provider-\u003egetAuthorizationUrl([\n    'p' =\u003e 'b2c_1_siup'\n]);\n```\n\n## Multipurpose refresh tokens - *experimental*\nIn cause that you need to access multiple resources (like your API and Microsoft Graph), you can use multipurpose [refresh tokens](https://msdn.microsoft.com/en-us/library/azure/dn645538.aspx). Once obtaining a token for first resource, you can simply request another token for different resource like so:\n```php\n$accessToken2 = $provider-\u003egetAccessToken('refresh_token', [\n    'refresh_token' =\u003e $accessToken1-\u003egetRefreshToken(),\n    'resource' =\u003e 'http://urlOfYourSecondResource'\n]);\n```\nAt the moment, there is one issue: When you make a call to your API and the token has expired, it will have the value of `$provider-\u003eurlAPI` which is obviously wrong for `$accessToken2`. The solution is very simple - set the `$provider-\u003eurlAPI` to the resource which you want to call. This issue will be addressed in future release. **Please note that this is experimental and wasn't fully tested.**\n\n## Known users\nIf you are using this library and would like to be listed here, please let us know!\n- [TheNetworg/DreamSpark-SSO](https://github.com/thenetworg/dreamspark-sso)\n\n## Contributing\nWe accept contributions via [Pull Requests on Github](https://github.com/thenetworg/oauth2-azure).\n\n## Credits\n- [Jan Hajek](https://github.com/hajekj) ([TheNetw.org](https://thenetw.org))\n- [Vittorio Bertocci](https://github.com/vibronet) (Microsoft)\n    - Thanks for the splendid support while implementing #16\n- [Martin Cetkovský](https://github.com/mcetkovsky) ([cetkovsky.eu](https://www.cetkovsky.eu)]\n- [All Contributors](https://github.com/thenetworg/oauth2-azure/contributors)\n\n## Support\nIf you find a bug or encounter any issue or have a problem/question with this library please create a [new issue](https://github.com/TheNetworg/oauth2-azure/issues).\n\n## License\nThe MIT License (MIT). Please see [License File](https://github.com/thenetworg/oauth2-azure/blob/master/LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthenetworg%2Foauth2-azure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthenetworg%2Foauth2-azure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthenetworg%2Foauth2-azure/lists"}