PHPackages                             itk-dev/openid-connect - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. itk-dev/openid-connect

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

itk-dev/openid-connect
======================

OpenID connect configuration package

5.0.0(1mo ago)174.0k↓33.9%2MITPHPPHP ^8.3CI passing

Since Mar 12Pushed 3w ago3 watchersCompare

[ Source](https://github.com/itk-dev/openid-connect)[ Packagist](https://packagist.org/packages/itk-dev/openid-connect)[ RSS](/packages/itk-dev-openid-connect/feed)WikiDiscussions develop Synced yesterday

READMEChangelog (10)Dependencies (45)Versions (31)Used By (2)

OpenID Connect
==============

[](#openid-connect)

[![Github](https://camo.githubusercontent.com/153c9bc159dd6b4b9841872f74e63da42cfd5aabb3888cf4c0c9fb8860855e62/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f736f757263652d69746b2d2d6465762f6f70656e69642d2d636f6e6e6563742d626c75653f7374796c653d666c61742d737175617265)](https://github.com/itk-dev/openid-connect)[![Release](https://camo.githubusercontent.com/d6ad32ae9f7402c378c5a5e138b3641283a7a7f95bbffd83ce75f98847c03298/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f69746b2d6465762f6f70656e69642d636f6e6e6563742e7376673f7374796c653d666c61742d737175617265266c6162656c3d72656c65617365)](https://packagist.org/packages/itk-dev/openid-connect)[![PHP Version](https://camo.githubusercontent.com/4a38f730ed5b2bded718ff0f61a2d12446fda183bccf37771bc7e7975bc0de27/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f69746b2d6465762f6f70656e69642d636f6e6e6563742e7376673f7374796c653d666c61742d73717561726526636f6c6f72423d253233383839324246)](https://www.php.net/downloads)[![Build Status](https://camo.githubusercontent.com/bc452142cc887e5afe0523904f2256aa09ce4698fc9843b0458b08398bb1f4de/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f69746b2d6465762f6f70656e69642d636f6e6e6563742f7068702e79616d6c3f6272616e63683d646576656c6f70266c6162656c3d4349266c6f676f3d676974687562267374796c653d666c61742d737175617265)](https://github.com/itk-dev/openid-connect/actions/workflows/php.yaml?query=branch%3Adevelop)[![Codecov Code Coverage](https://camo.githubusercontent.com/c6ac006d301e644cdfa5155dcc1531eccdfbc5c51222bf066a771e9f0d094ae3/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f67682f69746b2d6465762f6f70656e69642d636f6e6e6563743f6c6162656c3d636f6465636f76266c6f676f3d636f6465636f76267374796c653d666c61742d737175617265)](https://codecov.io/gh/itk-dev/openid-connect)[![Mutation Score](https://camo.githubusercontent.com/ac747a9c260c2af86007871e515f28350d6a34b4c6820b8c7c3d102784c670de/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742d737175617265266c6162656c3d6d75746174696f6e25323073636f72652675726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d25324669746b2d6465762532466f70656e69642d636f6e6e656374253246646576656c6f70)](https://dashboard.stryker-mutator.io/reports/github.com/itk-dev/openid-connect/develop)[![Read License](https://camo.githubusercontent.com/e6cba48c5cfeae803558d221e0fcedd847e4c33842644f2c8bd076a0598bf3cc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f69746b2d6465762f6f70656e69642d636f6e6e6563742e7376673f7374796c653d666c61742d73717561726526636f6c6f72423d6461726b6379616e)](https://github.com/itk-dev/openid-connect/blob/master/LICENSE.md)[![Package downloads on Packagist](https://camo.githubusercontent.com/9a108986b7bad8aeb3cd1bc3e95bd6b14b089dac51cf9ad41cd76682a2ede474/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f69746b2d6465762f6f70656e69642d636f6e6e6563742e7376673f7374796c653d666c61742d73717561726526636f6c6f72423d6461726b6d6167656e7461)](https://packagist.org/packages/itk-dev/openid-connect/stats)

Composer package for configuring OpenID Connect via [OpenID Connect Discovery document](https://openid.net/specs/openid-connect-discovery-1_0.html).

This library is made and tested for use with [Azure AD B2C](https://docs.microsoft.com/en-us/azure/active-directory-b2c/)but should be usable for other OpenID Connect providers.

References
----------

[](#references)

- [OpenID Connect Implicit Client Implementer's Guide 1.0](https://openid.net/specs/openid-connect-implicit-1_0.html)
- [Azure Active Directory B2C documentation](https://docs.microsoft.com/en-us/azure/active-directory-b2c/)
- [Web sign-in with OpenID Connect in Azure Active Directory B2C](https://docs.microsoft.com/en-us/azure/active-directory-b2c/openid-connect#send-authentication-requests)

Usage
-----

[](#usage)

### Framework

[](#framework)

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

- Symfony: [itk-dev/openid-connect-bundle](https://github.com/itk-dev/openid-connect-bundle)
- (Archived) Drupal: [itk-dev/itkdev\_openid\_connect\_drupal](https://github.com/itk-dev/itkdev_openid_connect_drupal)

### Direct Installation

[](#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](https://www.php-fig.org/psr/psr-6/). Look to [PHP Cache](http://www.php-cache.com/en/latest/) for documentation and implementations.

### Direct usage

[](#direct-usage)

#### Flow

[](#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

[](#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://app.example.org', // 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!
]);
```

##### HTTP timeout, proxy, and TLS verification

[](#http-timeout-proxy-and-tls-verification)

This library extends `league/oauth2-client`, which uses Guzzle for HTTP. To bound how long a request to the IdP can take (recommended for production), pass `timeout` (seconds) in the constructor `$options`:

```
$provider = new OpenIdConfigurationProvider([
    // ... required options ...
    'timeout' => 5,
    'proxy' => 'http://proxy.example.com:8080',
    'verify' => true, // only consulted by Guzzle when proxy is set
]);
```

`league/oauth2-client` whitelists exactly these three keys (`timeout`, `proxy`, `verify`) and forwards them to the underlying Guzzle client. Other Guzzle options (e.g. `connect_timeout`) are silently dropped.

> **Why Guzzle and not Symfony HttpClient?**`league/oauth2-client` hard-types its HTTP client as `GuzzleHttp\ClientInterface`. Symfony HttpClient implements PSR-18 / HTTPlug, not Guzzle's interface, and there is no maintained adapter going Symfony → Guzzle. To plug in a non-Guzzle client you would need to write such an adapter yourself and pass it via `$collaborators['httpClient']` to the constructor.

##### Leeway

[](#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:

- [firebase/php-jwt](https://github.com/firebase/php-jwt#example)Last entry in the example mentions the leeway option.
- [JWT documentation](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef)

#### Non-authorized requests

[](#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](https://docs.microsoft.com/en-us/azure/active-directory-b2c/openid-connect#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

[](#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 be thrown.
try {
    $claims = $provider->validateIdToken($request->query->get('id_token'), $session->get('oauth2nonce'));
    // Authentication successful
} catch (OpenIdConnectExceptionInterface $exception) {
    // Handle failed authentication
} finally {
    $this->session->remove('oauth2nonce');
}
```

### Exception handling

[](#exception-handling)

Every exception thrown from a public method of this library implements `\ItkDev\OpenIdConnect\Exception\OpenIdConnectExceptionInterface`. Catch the marker to handle any OIDC failure with a single block, or scope to a more specific type when you need to discriminate:

```
use ItkDev\OpenIdConnect\Exception\OpenIdConnectExceptionInterface;

try {
    $claims = $provider->validateIdToken($idToken, $nonce);
} catch (OpenIdConnectExceptionInterface $e) {
    // Cause is preserved via $e->getPrevious()
}
```

Concrete exception classes extend the SPL type that describes the failure category, so a `catch` block scoped to that SPL type will also match:

SPL parentConcrete typesCategory`\RuntimeException``CacheException`, `HttpException`, `JsonException`, `DecodeException`, `JwksException`, `CodeException`, `ValidationException`, `ClaimsException`, `MetadataException`Network, cache, token validation, claims mismatch — transient or data-shape failures`\LogicException``BadUrlException`, `IllegalSchemeException`, `MissingParameterException`Programmer/config bugs — should be fixed in code`\InvalidArgumentException``ConfigurationException`, `NegativeCacheDurationException`, `NegativeLeewayException`Invalid input to the constructor / setters`HttpException` additionally implements PSR-18's `Psr\Http\Client\ClientExceptionInterface`, so existing PSR-18-aware consumers can keep catching on the standard PSR marker.

Every wrap site preserves the underlying cause via `$previous`, so `$e->getPrevious()` walks back to the originating Guzzle, firebase/php-jwt or PSR-6 cache exception.

> **Upgrading from 4.x:** the concrete exceptions no longer extend the abstract `ItkOpenIdConnectException`. Catches written as `catch (ItkOpenIdConnectException $e)` will not match anything thrown by 5.0+ code — migrate to `catch (OpenIdConnectExceptionInterface $e)`. The abstract class itself is kept through 5.x as a documented alias (`@deprecated`); removal is scheduled for 6.0.

Development Setup
-----------------

[](#development-setup)

A `docker-compose.yml` file with a PHP 8.3+ image is included in this project. A [Taskfile](https://taskfile.dev/) 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

[](#running-all-ci-checks)

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

```
task pr:actions
```

### Unit Testing

[](#unit-testing)

```
task test
```

### Test Matrix

[](#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](https://github.com/mockery/mockery) to mock [public static methods](http://docs.mockery.io/en/latest/reference/public_static_properties.html?highlight=static)in 3rd party libraries like the `JWT::decode` method from `firebase/jwt`.

### Mutation Testing

[](#mutation-testing)

Line coverage shows which code the tests *execute*; mutation testing shows which code they actually *verify*. [Infection](https://infection.github.io/)applies small changes (mutants) to the source code — flipping a comparison, removing a method call — and runs the test suite against each one. If the tests still pass, the mutant "escaped": a potential bug the tests would not catch.

```
task test:mutation
```

The minimum mutation score (`minCoveredMsi`) is defined in `infection.json5`and enforced both locally and in CI — no command line flags needed. CI annotates escaped mutants inline on pull requests, and results for `develop`are published to the [Stryker dashboard](https://dashboard.stryker-mutator.io/reports/github.com/itk-dev/openid-connect/develop), which also feeds the mutation score badge above. Detailed reports are written to `infection.log` and `infection.html` on each run.

### PHPStan Static Analysis

[](#phpstan-static-analysis)

```
task analyze
```

### Coding Standards

[](#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

[](#available-tasks)

Run `task --list` to see all available tasks.

CI
--

[](#ci)

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

Versioning
----------

[](#versioning)

We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/itk-dev/openid-connect/tags).

License
-------

[](#license)

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

###  Health Score

60

—

FairBetter than 98% of packages

Maintenance95

Actively maintained with recent releases

Popularity32

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity79

Established project with proven stability

 Bus Factor1

Top contributor holds 84% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~112 days

Recently: every ~21 days

Total

18

Last Release

31d ago

Major Versions

1.0.0 → 2.0.02021-06-04

2.3.0 → 3.0.02022-01-05

3.2.1 → 4.0.02025-01-11

4.1.2 → 5.0.02026-06-02

PHP version history (5 changes)1.0.0PHP &gt;=7.2.5

2.0.0PHP ^7.3|^8.0

3.0.0PHP ^7.4|^8.0|^8.1

3.1.0PHP ^8.1

4.0.0PHP ^8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/33924554?v=4)[ITK Development](/maintainers/itk-dev)[@itk-dev](https://github.com/itk-dev)

---

Top Contributors

[![turegjorup](https://avatars.githubusercontent.com/u/5631988?v=4)](https://github.com/turegjorup "turegjorup (221 commits)")[![lats1](https://avatars.githubusercontent.com/u/48216125?v=4)](https://github.com/lats1 "lats1 (20 commits)")[![rimi-itk](https://avatars.githubusercontent.com/u/11267554?v=4)](https://github.com/rimi-itk "rimi-itk (16 commits)")[![jekuaitk](https://avatars.githubusercontent.com/u/78410897?v=4)](https://github.com/jekuaitk "jekuaitk (6 commits)")

---

Tags

azureb2copenid-connectphp-library

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/itk-dev-openid-connect/health.svg)

```
[![Health](https://phpackages.com/badges/itk-dev-openid-connect/health.svg)](https://phpackages.com/packages/itk-dev-openid-connect)
```

###  Alternatives

[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k15](/packages/tempest-framework)[google/auth

Google Auth Library for PHP

1.4k294.2M218](/packages/google-auth)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

751291.4k43](/packages/civicrm-civicrm-core)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.9M736](/packages/sylius-sylius)[thenetworg/oauth2-azure

Azure Active Directory OAuth 2.0 Client Provider for The PHP League OAuth2-Client

25310.7M83](/packages/thenetworg-oauth2-azure)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
