Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Openid Connect Claims Laravel Package

league/openid-connect-claims

Provides strongly-typed PHP value objects for OpenID Connect claims, making it easy to build, validate, and serialize standard and custom claims for OIDC ID tokens and userinfo responses. Part of the League of Extraordinary Packages.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is small and purpose-built: it gives you a typed, object-oriented view over the claim set inside an OpenID Connect ID token. It is not a JWT decoder, a token verifier, or an OAuth2 client — it only models the claims payload.

Minimal setup:

composer require league/openid-connect-claims

Where to look first:

  1. README.md — confirm the current class name (src/ is the source of truth; the primary type is an ID-claims-set object that wraps an associative array of decoded claims).
  2. src/ — read the main claims-set class and any interface it implements. The public surface is mostly immutable getters plus an array/toArray() style accessor.
  3. composer.json — note the PHP constraint and the absence of dependencies. It is a standalone value object, so it drops into any stack without pulling in PSR-7, JWT libraries, etc.

First use case — take the payload you already obtained from your OAuth2 client, wrap it, and read standard claims:

use League\OpenIDConnectClaims\IdClaimsSet;

// $payload is the already-decoded JSON body of the ID token
// (signature verification must have happened elsewhere).
$claims = new IdClaimsSet($payload);

$subject  = $claims->getSubject();       // "sub"
$issuer   = $claims->getIssuer();        // "iss"
$audience = $claims->getAudience();      // "aud"
$email    = $claims->getClaim('email');  // non-modelled / optional claims

Treat the object as the boundary between “raw array coming off the wire” and “typed claims your application code consumes.” That single conversion is the package’s whole reason to exist.

Implementation Patterns

Wrap, don’t leak, the raw array. The most common day-to-day pattern is to construct the claims set once — right after your OAuth2/OIDC client exchanges the code — and pass the object (or a domain DTO built from it) through the rest of the request. Controllers, middleware, and services should not be reading $payload['sub'] directly.

Custom provider integration. With league/oauth2-client, subclass or decorate your provider so getResourceOwner()/your own accessor returns an IdClaimsSet:

class MyIdpProvider extends AbstractProvider
{
    public function getIdClaims(AccessToken $token): IdClaimsSet
    {
        $payload = $this->decodeIdToken($token); // your JWT verify + decode
        return new IdClaimsSet($payload);
    }
}

Keep verification separate and explicit. The claim set is a passive model. Your pipeline should be:

  1. Receive ID token.
  2. Verify signature (JWKS / issuer keys).
  3. Decode payload.
  4. Build IdClaimsSet.
  5. Validate iss, aud, exp, nonce against expectations.
  6. Build your domain user from the claims.

Steps 2 and 5 are your responsibility — do not assume the package performs them.

Validation helper/service. Since the object is immutable and cheap, make a small IdClaimsValidator that takes an IdClaimsSet plus expected issuer/audience/nonce and returns a boolean or throws. This keeps policy out of the value object and makes the rules testable:

final class IdClaimsValidator
{
    public function __construct(
        private string $expectedIssuer,
        private string $expectedAudience,
    ) {}

    public function assertValid(IdClaimsSet $claims): void
    {
        if ($claims->getIssuer() !== $this->expectedIssuer) {
            throw new InvalidIdToken('issuer mismatch');
        }
        if (!in_array($this->expectedAudience, (array) $claims->getAudience(), true)) {
            throw new InvalidIdToken('audience mismatch');
        }
        if ($claims->getExpirationTime() <= time()) {
            throw new InvalidIdToken('token expired');
        }
    }
}

Session / cache pattern. Because the object is a simple wrapper, serialize it as the raw array (toArray() / getClaims()) when persisting to session or cache, and reconstruct on read. Avoid serializing the object itself — that couples your storage format to an unmaintained class.

Extension via composition. If you need convenience getters the package lacks (e.g. getName(), getEmail()), add them on your own DTO or a thin wrapper rather than subclassing the claims set. Subclassing buys you nothing here and makes upgrades/migrations harder.

Testing pattern. Since the constructor takes a plain array, tests are trivial: build an IdClaimsSet from a fixture array and assert against your domain-building logic. No external services, no mocking of the package needed.

Gotchas and Tips

  • It does not verify JWTs. The biggest trap for newcomers: holding an IdClaimsSet says nothing about whether the token was signed by the IdP. Parse and verify elsewhere (e.g. firebase/php-jwt, web-token/jwt-framework) before constructing the claims set.
  • No built-in policy validation. Don’t assume getExpirationTime() throws on expiry or that issuer/audience checks happen automatically. Do them yourself, every time.
  • Audience is polymorphic. Per spec, aud may be a string or an array of strings. Normalize (array) $claims->getAudience() before comparing — a strict === against a string will bite you on multi-audience tokens.
  • NumericDate types. OIDC time claims (exp, iat, auth_time) are seconds-since-epoch numeric values. If the package returns them as-is, do not compare against DateTime objects; convert explicitly. Watch for integer/string coercion if the payload came through json_decode with associative arrays that were re-encoded.
  • Unmaintained since 2016. No releases since May 2016, no dependents, low activity. It will install fine on modern PHP in most cases because it’s dependency-free, but audit it against your PHP version constraint and be prepared to vendor-fork it. For a greenfield project, a hand-rolled 30-line value object gives you the same ergonomics with none of the abandonment risk; this package earns its place where you want a spec-name mapping already done.
  • Case and naming. Claims are lowercase in OIDC (sub, aud, auth_time). A generic getClaim('Auth_Time') will quietly miss. Stick to the spec names.
  • Optional claims are optional. email, name, picture, etc. are only present if the IdP was asked for them via scopes. Always null-check; don’t let a missing email blow up your user-mapping code.
  • Immutable by design. There is no setter, so don’t try to “fix up” claims on the object after construction — copy/rebuild the array instead. This is a feature; it keeps the value object safe to pass around.
  • Debugging tip. When an issuer or audience check fails unexpectedly, dump $claims->toArray() (or getClaims()) rather than individual getters — the raw array exposes typos and type coercions that the typed getters hide.
  • Extension point. If you need custom claims, use the generic accessor / array view rather than expecting dedicated getters for every provider-specific field. The package models the standard set; vendor-specific claims are best handled at the domain-mapping layer, not by patching the claims object.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package