Skip to content

D3strukt0r/oauth2-openid

OpenID provider for OAuth 2.0 Client

This package provides OpenID OAuth 2.0 support for the PHP League's OAuth 2.0 Client.

Project

License Version Version (including pre-releases) Downloads on Packagist Required PHP version

master-branch (alias stable, latest)

GH Action CI/CD Coveralls Scrutinizer build status Scrutinizer code quality Codacy grade Docs build status

This package is compliant with PSR-1, PSR-2 and PSR-4. If you notice compliance oversights, please send a patch via pull request.

Getting Started

Prerequisites

The following versions of PHP are supported.

  • 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).

Installing

To install, use composer:

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:

$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:

$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:

$authorizationUrl = $provider->getAuthorizationUrl(['approval_prompt' => 'force']);

Now you have everything you need to refresh an access token using a refresh token:

$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:

$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.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE.txt file for details

Acknowledgments

  • Hat tip to anyone whose code was used
  • Inspiration
  • etc

About

OpenID OAuth 2.0 Client Provider for The PHP League OAuth2-Client

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages