Download the PHP package bbs-lab/laravel-okta without Composer
On this page you can find all versions of the php package bbs-lab/laravel-okta. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download bbs-lab/laravel-okta
More information about bbs-lab/laravel-okta
Files in bbs-lab/laravel-okta
Package laravel-okta
Short Description Framework-agnostic Okta SSO for Laravel: the Socialite Okta driver, login/callback/logout flow, lifecycle hooks and a pluggable panel seam that the nova-okta and filament-okta adapters build on.
License MIT
Homepage https://github.com/BBS-Lab/laravel-okta
Informations about the package laravel-okta
Laravel Okta
Framework-agnostic Okta SSO for Laravel. It registers the socialiteproviders/okta driver, wires the login / callback / logout flow, exposes login-lifecycle hooks, and drives everything through a small panel seam so the same Okta capability can back any admin panel.
Most apps install an adapter rather than this package directly:
- bbs-lab/nova-okta — Laravel Nova
- bbs-lab/filament-okta — Filament
Install this package directly only when you are wiring Okta into a custom panel (see Building an adapter).
Requirements
- PHP 8.2+
- Laravel 11, 12 or 13
Installation
The service provider is auto-discovered.
Okta application
In your Okta admin, create an OIDC / Web application and set:
- Sign-in redirect URI:
{APP_URL}/{prefix}/authorization-code/callback - Sign-out redirect URI:
{APP_URL}/{prefix}/authorization-code/callback/logout
where {prefix} is the panel's route prefix (empty for the base package's default plain-application panel; the panel path for an adapter). These paths are configurable — see Routes.
Credentials
Add the okta block to config/services.php (this package intentionally does not own your credentials):
OKTA_BASE_URL is the bare org URL (no /oauth2). Keep the redirect key present (it may be null).
OKTA_REDIRECT_URI is optional. The redirect URI is a route this package generates, so when
it is not set the package derives it from the panel's callback route automatically — you only
declare the matching Sign-in redirect URI in your Okta application. Set OKTA_REDIRECT_URI
(and the config value) only to override the derived URL, e.g. when the public URL differs from
APP_URL behind a reverse proxy.
Routes
An adapter (or the base package on its own) mounts four routes for its panel via OktaRoutes::register():
| Route (default path) | Name | Purpose |
|---|---|---|
GET authorization-code/redirect |
{panel}.login |
Redirects to Okta (start login) — the URL your Okta button points at. |
GET authorization-code/callback |
{panel}.callback |
Login callback — resolves the user and logs them in (this is the Sign-in redirect URI target). |
GET authorization-code/logout |
{panel}.logout |
Logs out locally, and — when sso_logout is on — via Okta's OIDC end-session (start logout). |
GET authorization-code/callback/logout |
{panel}.callback.logout |
Okta's post-logout landing (sign-out redirect). |
{panel} is the panel's route-name prefix (okta for the default panel, nova-okta / filament-okta for the adapters). Paths are mounted under the panel's route prefix, so the login route for a Nova panel at /nova is nova/authorization-code/redirect.
The paths are configurable (the route names never change, so route('{panel}.login') and the derived redirect URI follow automatically). Set them under okta.paths in config (see below) or, for Filament, per panel with OktaPlugin::make()->paths(...). Changing the callback path changes the OIDC redirect URI you must whitelist in Okta.
Configuration
Everything works out of the box. To tweak behaviour, publish the config:
There is deliberately no user-mapping config — resolution uses your auth guard's own user provider, and everything else is a hook (below).
User resolution & lifecycle
By default the package maps an Okta account to a local user through your auth guard's own
user provider (the Eloquent provider), matched by a verified email — no model or field config,
and it never creates a user. Everything else is a hook you register on the Okta facade (e.g.
in a service provider's boot()), so you opt into exactly what you need:
The flow is: resolve → authorizeUserToLogin → beforeLogin → log in → afterLogin
(or onLoginDenied when resolution/authorization fails).
⚠️
Okta::resolveUserUsing()fully replaces the lookup — it short-circuits the default resolver, so the built-in verified-email gate and stable-id matching no longer run. Only use it when you need custom resolution, and check the claims yourself. In particular, do not provision a user from an unverified email:For the common "match on the stable Okta id" case, prefer the built-in
identifierconfig below instead of a custom resolver.
Matching by a stable id (optional)
Okta issues a stable subject id (the OIDC sub, $oktaUser->getId()). If you store it on your
users table, set the column in config and the default resolver matches on it first — so a
login survives the user's email changing — then falls back to a verified email, and backfills
the column the first time it matches by email:
Add the column with a migration (make it unique — the id match trusts a single row). A
ready-made okta_id migration ships with the package:
(adjust it if your column is named differently). An account matched by this id signs in without
re-checking the email (the link is already trusted), so require_verified_email only gates the
email-fallback path — and a link is only ever backfilled from a verified email.
The default resolver does not gate — it signs in any user it finds by email. Deciding who may sign in is the app's job (a hook above, or a custom resolver below). Set an authorization rule for any admin panel.
Gating with a reusable resolver (extend, don't rewrite)
When several projects share the same sign-in policy, prefer a small resolver that extends
DefaultOktaUserResolver and adds the gate on top — you keep the verified-email check, the stable-id
matching and the backfill, and only add your policy. Bind it in a service provider:
Prefer
Okta::authorizeUserToLogin()for a per-project gate; reach for a resolver subclass only when the same policy is shared across projects. Avoid a from-scratch resolver that re-implements an email-only lookup — it silently drops the verified-email gate and the stable-id matching.
The authorizeUserToLogin / beforeLogin / afterLogin / onLoginDenied hooks run on top, so use
them for cross-cutting side effects (audit, a last-login stamp via afterLogin).
Building an adapter
An adapter binds a single seam — the BBSLab\LaravelOkta\Contracts\OktaPanel contract — and then
registers the routes for it. Everything panel-specific lives on the panel (guard, URLs, routing,
the Socialite driver and the behaviour flags), never in a global the base reads directly — so several
panels can run side by side with different Okta configurations, each resolving its own panel per
request.
For a single-panel adapter whose settings come from config('okta.*'), extend ConfigOktaPanel and
supply only the routing + guard methods:
For a multi-panel adapter, implement OktaPanel directly and return each panel's own values —
including socialiteDriver() (a distinct registered driver for a panel with its own Okta app),
ssoLogout(), requireVerifiedEmail(), identifierColumn(), identifierUpdate() and
path(OktaRoute $route) (the URI each route mounts at, so each panel can carry its own — return
$route->defaultPath() to keep the defaults).
Bind it and register the routes from wherever your panel's path and middleware are known:
Render an Okta button in your login screen that points at route('my-okta.login'), and point your
logout link at route('my-okta.logout'). That is the whole adapter surface.
When more than one panel is active, bind OktaPanel to a closure that returns the panel for the
current request (e.g. from the panel your framework is currently serving), and call
OktaRoutes::register() once per panel with a distinct routeName().
Session flags
On a successful Okta login the package sets two session keys:
okta_authenticated— a signal meaning "this session authenticated via Okta" (not "MFA was performed"). A forced-2FA-enrolment guard can read it to skip enrolment for SSO users — but only do so if your Okta application actually enforces MFA, otherwise a single-factor Okta login would downgrade your 2FA.okta_id_token— the OIDC id_token, used to build the end-session (logout) URL.
Testing
Browser & live e2e
The browser (Pest v4) and live Playwright suites cover the pre-redirect login UX (the Okta button and the start of the OIDC redirect); the full SSO round-trip needs a real Okta org.
Security
- Verified emails. The default resolver rejects unverified Okta emails (
require_verified_email). If you replace the resolver, keep an equivalent check. - Logout is a
GET(so it can be a user-menu external link), which is why it relies on the framework's defaultSESSION_SAME_SITE=laxto prevent cross-site logout. Keep SameSite atlax/strict; if you set it tonone, wire logout as aPOSTform instead.
Please email [email protected] for security issues instead of the issue tracker.
Changelog
See CHANGELOG.md.
Contributing
See CONTRIBUTING.md.
Credits
License
The MIT License (MIT). See LICENSE.md.
All versions of laravel-okta with dependencies
illuminate/contracts Version ^11.0 || ^12.0 || ^13.0
illuminate/database Version ^11.0 || ^12.0 || ^13.0
illuminate/http Version ^11.0 || ^12.0 || ^13.0
illuminate/support Version ^11.0 || ^12.0 || ^13.0
laravel/socialite Version ^5.0
socialiteproviders/okta Version ^4.4
spatie/laravel-package-tools Version ^1.16