Skip to content

itk-dev/openid-connect

Repository files navigation

OpenID Connect

Github Release PHP Version Build Status Codecov Code Coverage Read License Package downloads on Packagist

Composer package for configuring OpenID Connect via OpenID Connect Discovery document.

This library is made and tested for use with Azure AD B2C but should be usable for other OpenID Connect providers.

References

Usage

Framework

If you are looking to use this in a Symfony or Drupal project you should use either:

Direct Installation

To install this library directly run

composer require itk-dev/openid-connect

To use the library you must provide a cache implementation of PSR-6: Caching Interface. Look to PHP Cache for documentation and implementations.

Direct usage

Flow

When a user wishes to authenticate themselves, we create an instance of OpenIdConfigurationProvider and redirect them to the authorization url this provides. Here the user can authenticate and if successful be redirected back the redirect uri provided. During verification of the response from the authorizer we can extract information about the user from the id_token, depending on which claims are supported.

Configuration

To use the package import the namespace, create and configure a provider

require_once __DIR__.'/vendor/autoload.php';

use ItkDev\OpenIdConnect\Security\OpenIdConfigurationProvider;

$provider = new OpenIdConfigurationProvider([
    'redirectUri' => 'https://some.url', // Absolute url to where the user is redirected after a successful login
    'openIDConnectMetadataUrl' => 'https:/.../openid-configuration', // url to OpenId Discovery document
    'cacheItemPool' => 'Psr6/CacheItemPoolInterface', // Implementation of CacheItemPoolInterface for caching above discovery document
    'clientId' => 'client_id', // Client id assigned by authorizer
    'clientSecret' => 'client_secret', // Client password assigned by authorizer
    // optional values
    'leeway' => 30, // Defaults to 10 (seconds)
    'cacheDuration' => 3600, // Defaults to 86400 (seconds)
    'allowHttp' => true, // Defaults to false. Allow OIDC urls with http scheme. Use only during development!
]);
Leeway

To account for clock skew times between the signing and verifying servers, you can set a leeway when configuring the provider. It is recommended that leeway should not be bigger than a few minutes.

Defaults to 10 seconds

For more information see the following:

Non-authorized requests

Non-authorized requests should be redirected to the authorization url.

To generate the authorization url you must supply "state" and "nonce":

State: "A value included in the request that's also returned in the token response. It can be a string of any content that you want. A randomly generated unique value is typically used for preventing cross-site request forgery attacks. The state is also used to encode information about the user's state in the application before the authentication request occurred, such as the page they were on."

Nonce: "A value included in the request (generated by the application) that is included in the resulting ID token as a claim. The application can then verify this value to mitigate token replay attacks. The value is typically a randomized unique string that can be used to identify the origin of the request."

See: Send authentication requests

You must persist these locally so that they can be used to validate the token when the user is redirected back to your application.

// Get "state" and "nonce"
$state = $provider->generateState();
$nonce = $provider->generateNonce();

// Save to session
$session->set('oauth2state', $state);
$session->set('oauth2nonce', $nonce);

$authUrl = $provider->getAuthorizationUrl(['state' => $state, 'nonce' => $nonce]);

// redirect to $authUrl

Note that the default response type and mode is set in OpenIdConfigurationProvider.php

'response_type' => 'id_token',
'response_mode' => 'query',

Verify authorized requests

The authorization service will redirect the user back to the redirectUri. This should be an endpoint in your application where you validate the token and the user.

Load the "state" and "nonce" from local storage and validate against the request values

// Validate that the request state and session state match
$sessionState = $this->session->get('oauth2state');
$this->session->remove('oauth2state');
if (!$sessionState || $request->query->get('state') !== $sessionState) {
    throw new ValidationException('Invalid state');
}

// Validate the id token. This will validate the token against the keys published by the
// provider (Azure AD B2C). If the token is invalid or the nonce doesn't match an
// exception will thrown.
try {
    $claims = $provider->validateIdToken($request->query->get('id_token'), $session->get('oauth2nonce'));
    // Authentication successful
} catch (ItkOpenIdConnectException $exception) {
    // Handle failed authentication
} finally {
    $this->session->remove('oauth2nonce');
}

Development Setup

A docker-compose.yml file with a PHP 8.3+ image is included in this project. A Taskfile is used to run common development tasks.

To set up the project:

task setup

This starts the Docker containers and installs Composer dependencies.

Running All CI Checks

To run all checks locally (coding standards, static analysis, tests):

task pr:actions

Unit Testing

task test

Test Matrix

Run the test suite across all supported PHP versions (8.3, 8.4, 8.5) with both lowest and stable dependencies, mirroring the CI matrix:

task test:matrix

This runs PHPUnit with coverage for each combination and prints a summary of pass/fail results.

The test suite uses Mockery to mock public static methods in 3rd party libraries like the JWT::decode method from firebase/jwt.

PHPStan Static Analysis

task analyze

Coding Standards

Check all coding standards:

task lint

Fix PHP coding standards (php-cs-fixer):

task lint:php:fix

Fix Markdown files:

task lint:markdown:fix

Fix YAML files:

task lint:yaml:fix

Available Tasks

Run task --list to see all available tasks.

CI

GitHub Actions are used to run the test suite and code style checks on all PRs.

Versioning

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

License

This project is licensed under the MIT License - see the LICENSE.md file for details

About

Composer package for configuring OpenID Connect via OpenID Connect Discovery document.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages