devadamlar / laravel-oidc
Installs: 1 722
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 1
Forks: 1
Open Issues: 0
Requires
- php: ^8.1
- ext-openssl: *
- firebase/php-jwt: ^6.10.1
- guzzlehttp/guzzle: ^7.8.1
- illuminate/auth: >=10.15
- illuminate/cache: >=10.15
- illuminate/config: >=10.15
- illuminate/contracts: >=10.15
- illuminate/events: >=10.15
- illuminate/filesystem: >=10.15
- illuminate/http: >=10.15
- illuminate/support: >=10.15
- phpseclib/phpseclib: ^3.0.37
Requires (Dev)
- larastan/larastan: ^2.9.7
- laravel/pint: ^1.16
- nunomaduro/collision: ^7.10
- orchestra/testbench: ^8.23.2
- phpunit/phpunit: ^10.5.21
README
Overview
This package allows Laravel applications to authenticate users using JWT tokens from OpenID Connect (OIDC) providers. It integrates smoothly with Laravel's built-in authentication system and offers flexibility for multi-tenant architectures by allowing configurations to be tailored on a per-guard basis.
Installation
composer require devadamlar/laravel-oidc
You can publish the configuration file to make changes:
php artisan vendor:publish --provider="DevAdamlar\LaravelOidc\LaravelOidcServiceProvider"
Usage
You start by defining a guard in the config/auth.php
file.
'guards' => [ 'api' => [ 'driver' => 'oidc', 'provider' => 'users', 'issuer' => 'https://your-auth-server.com', // must contain /.well-known/openid-configuration ], ],
Note that the guard includes the issuer
URL, which is the base URL of your OIDC provider.
This URL is used to fetch the discovery document containing the public keys.
The package will cache the public keys from the discovery document,
ensuring no repetitive requests are made to the OIDC provider each time a token is verified.
Alternatively, you can provide the public key directly in the configuration file avoiding the need to fetch the discovery document.
'guards' => [ 'api' => [ 'driver' => 'oidc', 'provider' => 'users', 'public_key' => 'base64-encoded-der', // or '/path/to/public-key.pem' 'key_disk' => 'private-s3', // optional ], ],
Storage disk for the public key is set to the default disk defined in the filesystems
configuration file
but can be changed by setting key_disk
in the guard configuration or OIDC_KEY_DISK
environment variable.
When both the issuer URL and the public key are set for a guard, the package prioritizes the public key for verifying the tokens.
Authenticating Requests
You can use the auth
middleware with the defined guard to protect your routes.
For example, the following route will return the authenticated user if the request is authenticated with the api
guard
Route::middleware('auth:api')->get('/user', function (Request $request) { return auth()->user(); // User model });
Model retrieval
The model defined in the provider
must implement Illuminate\Contracts\Auth\Authenticatable
as the default User
model does.
It has to contain the sub
claim from the token as the auth identifier.
The attribute for auth identifier is the primary key of the model by default,
but you can change it by overriding the getAuthIdentifierName
method in the model:
use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { public function getAuthIdentifierName() { return 'auth_uuid'; } }
Global Configuration
You can set global configurations in the .env
file for the entire application.
For example, you can set the issuer URL and the public key in the .env
file as follows:
OIDC_ISSUER=https://your-auth-server.com OIDC_PUBLIC_KEY=/path/to/public-key.pem
This way, you can avoid repeating the same configurations for each guard: for each missing configuration in a guard, the package will fall back to the global configuration.
For issuer URLs, you can also set a shared base URL in the global configuration. The guard-level configuration can then extend this base URL with additional path segments. For example, you can set the base URL in the global configuration as follows:
OIDC_ISSUER=https://your-auth-server.com
And then extend it in the guard-level configuration as follows:
'guards' => [ 'api' => [ 'driver' => 'oidc', 'provider' => 'users', 'issuer' => 'tenant1', ], ],
In this case, the issuer URL for the api
guard will be https://your-auth-server.com/tenant1
.
If the guard-level issuer configuration is a full URL, it will override the base URL instead. For example, the following configuration:
'guards' => [ 'api' => [ 'driver' => 'oidc', 'provider' => 'users', 'issuer' => 'https://tenant1-auth-server.com', ], ],
will ignore whatever is set in the global configuration and use https://tenant1-auth-server.com
as the issuer URL.
You can publish the configuration file and refer to the documentation there for all available options:
php artisan vendor:publish --provider="DevAdamlar\LaravelOidc\LaravelOidcServiceProvider"
Every configuration option in the published file is also available as a guard-level configuration.
Introspection
Introspection is a process where the validity of a token is verified by sending it to the authorization server. This is an alternative to local validation, where the server checks the token's signature and claims itself in real-time.
Benefits of Introspection
- Revoke Checking: Introspection can check if a token has been revoked, which local validation cannot do.
- Opaque Tokens: It allows validation of opaque tokens that cannot be validated locally because they don't contain the required information.
- Dynamic Information: Introspection can provide real-time information about the token, ensuring up-to-date verification.
Basic Setup for Introspection
To enable introspection, configure the following in your .env
file:
OIDC_USE_INTROSPECTION=true OIDC_INTROSPECTION_AUTH_METHOD=client_secret_basic OIDC_CLIENT_ID=your-client-id OIDC_CLIENT_SECRET=your-client-secret
For a guard-level configuration, set the following:
'guards' => [ 'api' => [ 'driver' => 'oidc', 'provider' => 'users', 'issuer' => 'https://your-auth-server.com', 'use_introspection' => true, 'introspection_auth_method' => 'client_secret_basic', // [, 'client_secret_post', 'client_secret_jwt', 'private_key_jwt'] 'client_id' => 'your-client-id', 'client_secret' => 'your-client-secret', ], // Other guards... ],
JWKS URI Configuration
When using the private_key_jwt
auth method for token introspection, the issuer requires the RP’s public key or JWKS URI
to verify the JWT assertion sent by the RP. You can expose the app’s JWKS,
derived from private keys in the config file and guards, by setting a route path via OIDC_RP_JWKS_PATH
.
OIDC issuers can then use the route to validate JWT signatures sent during introspection.
OIDC_RP_JWKS_PATH=/jwks
Caching
The package caches the public keys, discovery document
to avoid repetitive requests to the OIDC provider.
The cache duration is set to 24 hours by default for production
environment
but can be changed in the configuration files or the .env
file.
OIDC_CACHE_TTL=1440
TODO
- Place coverage, build, security, maintainability badges
- Fix all PHPStan issues
- Incorporate git hooks
- Implement a CI/CD pipeline with GitHub Actions
- Add a contribution guide
- Dockerize the application
- Write integration tests
- Add a command to clear the cache
- Add a hook for token validation check
- Add a hook to clear the cache when the public keys change