OpenID provider for OAuth 2.0 Client
This package provides OpenID OAuth 2.0 support for the PHP League's
OAuth 2.0 Client., (*1)
Project, (*2)
, (*3)
master-branch (alias stable, latest), (*4)
, (*5)
This package is compliant with PSR-1, PSR-2 and PSR-4. If you notice compliance oversights, please send
a patch via pull request., (*6)
Getting Started
Prerequisites
The following versions of PHP are supported., (*7)
- PHP 7.1
- PHP 7.2
- PHP 7.3
- PHP 7.4
- HHVM
OpenID App will also need to be set up, which
will provide you with the {app-id}
and {app-secret}
required (see Usage below)., (*8)
Installing
To install, use composer:, (*9)
composer require d3strukt0r/oauth2-openid
Usage
Authorization Code Flow
$provider = new Generation2\OAuth2\Client\Provider\Generation2Provider([
'clientId' => '{app-id}', // The client ID assigned to you by the provider
'clientSecret' => '{app-secret}', // The client password assigned to you by the provider
'redirectUri' => 'https://example.com/callback-url',
]);
if (!empty($_GET['error'])) {
// Got an error, probably user denied access
unset($_SESSION['oauth2state']);
exit('Got error: '.htmlspecialchars($_GET['error_description']).' ('.htmlspecialchars($_GET['error']).')');
// If we don't have an authorization code then get one
} elseif (!isset($_GET['code'])) {
// Fetch the authorization URL from the provider; this returns the
// urlAuthorize option and generates and applies any necessary parameters
// (e.g. state).
$authorizationUrl = $provider->getAuthorizationUrl([
'scope' => 'user:id user:email',
]);
// Get the state generated for you and store it to the session.
$_SESSION['oauth2state'] = $provider->getState();
// Redirect the user to the authorization URL.
header('Location: '.$authorizationUrl);
exit;
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
// State is invalid, possible CSRF attack in progress
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
try {
// Try to get an access token using the authorization code grant.
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code'],
]);
// Use this to interact with an API on the users behalf
echo $token->getToken();
// Use this to get a new access token if the old one expires
echo $token->getRefreshToken();
// Exact timestamp when the access token will expire, and need refreshing
echo $token->getExpires();
// Optional: Now you have a token you can look up a users profile data
// We got an access token, let's now get the owner details
$ownerDetails = $provider->getResourceOwner($token);
// Use these details to create a new profile
printf('Hello %s!', $ownerDetails->getId());
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
// Failed to get the access token or user details.
exit($e->getMessage());
}
}
Refreshing a Token
Refresh tokens are only provided to applications which request offline access. You can specify offline access by setting
the accessType
option in your provider:, (*10)
$provider = new Generation2\OAuth2\Client\Provider\Generation2Provider([
'clientId' => '{app-id}', // The client ID assigned to you by the provider
'clientSecret' => '{app-secret}', // The client password assigned to you by the provider
'redirectUri' => 'https://example.com/callback-url',
]);
It is important to note that the refresh token is only returned on the first request after this it will be null
. You
should securely store the refresh token when it is returned:, (*11)
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $code
]);
// persist the token in a database
$refreshToken = $accessToken->getRefreshToken();
If you ever need to get a new refresh token you can request one by forcing the approval prompt:, (*12)
$authorizationUrl = $provider->getAuthorizationUrl(['approval_prompt' => 'force']);
Now you have everything you need to refresh an access token using a refresh token:, (*13)
$provider = new Generation2\OAuth2\Client\Provider\Generation2Provider([
'clientId' => '{app-id}', // The client ID assigned to you by the provider
'clientSecret' => '{app-secret}', // The client password assigned to you by the provider
'redirectUri' => 'https://example.com/callback-url',
]);
$newAccessToken = $provider->getAccessToken('refresh_token', [
'refresh_token' => $oldAccessToken->getRefreshToken()
]);
Scopes
If needed, you can include an array of scopes when getting the authorization url. Example:, (*14)
$authorizationUrl = $provider->getAuthorizationUrl([
'scope' => [
'user:id user:email',
]
]);
header('Location: ' . $authorizationUrl);
exit;
Running the tests
./vendor/bin/phpunit
Built With
Contributing
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us., (*15)
Versioning
We use SemVer for versioning. For the versions available, see the tags on this repository., (*16)
Authors
See also the list of contributors who participated in this project., (*17)
License
This project is licensed under the GNU General Public License v3.0 - see the LICENSE.txt file for details, (*18)
Acknowledgments
- Hat tip to anyone whose code was used
- Inspiration
- etc