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

Okta Laravel Package

socialiteproviders/okta

Okta OAuth provider for Laravel Socialite, part of the Socialite Providers collection. Adds Okta single sign-on to Laravel apps via simple driver registration and config, using standard Socialite flows. Lightweight, community-maintained, and easy to drop in.

Deep Wiki
Context7

Getting Started

This package is a Socialite driver, not a full auth system. You still own the routes, controller, user model, and session handling — the provider only handles the OAuth2/OIDC dance with Okta.

  1. Install the provider and the manager:

    composer require socialiteproviders/okta socialiteproviders/manager
    

    socialiteproviders/manager is what dispatches the SocialiteWasCalled event the provider hooks into. It is easy to forget and produces a confusing "Driver [okta] is not supported" error.

  2. Register the extend listener. On Laravel 11+ there is no EventServiceProvider by default, so put it in AppServiceProvider::boot():

    use Illuminate\Support\Facades\Event;
    use SocialiteProviders\Manager\SocialiteWasCalled;
    
    public function boot(): void
    {
        Event::listen(
            SocialiteWasCalled::class,
            \SocialiteProviders\Okta\OktaExtendSocialite::class.'@handle'
        );
    }
    

    On older Laravel, use the $listen array in app/Providers/EventServiceProvider.php instead.

  3. Configure the driver in config/services.php:

    'okta' => [
        'client_id'     => env('OKTA_CLIENT_ID'),
        'client_secret' => env('OKTA_CLIENT_SECRET'),
        'redirect'      => env('OKTA_REDIRECT_URI'),
        'base_url'      => env('OKTA_BASE_URL'), // https://dev-123456.okta.com
    ],
    
  4. Create the Okta app. In the Okta admin console create an OIDC Web Application, set the Sign-in redirect URI to exactly your callback URL (https://app.test/auth/okta/callback), and grant the scopes you intend to request (openid profile email by default).

  5. First use case — a two-route controller:

    Route::get('/auth/okta/redirect', fn () => Socialite::driver('okta')->redirect());
    Route::get('/auth/okta/callback', function () {
        $oktaUser = Socialite::driver('okta')->user();
    
        $user = User::updateOrCreate(
            ['okta_id' => $oktaUser->getId()],
            ['name' => $oktaUser->getName(), 'email' => $oktaUser->getEmail()]
        );
    
        Auth::login($user, remember: true);
        return redirect()->intended('/dashboard');
    });
    

Where to look first: this repository is a read-only subtree split of the SocialiteProviders/Providers monorepo. Issues and PRs belong there, not here. For behavior questions, read src/Provider.php and src/OktaExtendSocialite.php — they are short and are the source of truth for URL construction and claim mapping.

Implementation Patterns

Standard web login (redirect + callback). The canonical flow above. Keep the callback route behind the web middleware so the state parameter can be validated against the session. Return a redirect to intended() so deep links survive the round trip.

Use sub as the identity key, not email. Okta's sub claim is stable per user per authorization server. Email addresses change on marriage/renaming and are not unique across all Okta configurations. Store okta_id (mapped from sub) as a unique column and treat email as a mutable attribute.

Stateless for APIs and SPAs. If you are authenticating a mobile app or a separate SPA and doing the token exchange server-side, call Socialite::driver('okta')->stateless()->user(). You lose CSRF protection from state, so only do this when the client is already handling its own flow.

Multiple tenants / multiple Okta orgs. The driver reads from services.okta at resolution time, so you can temporarily override it before calling the driver:

config(['services.okta' => array_merge(
    config('services.okta'),
    ['base_url' => $tenant->okta_domain, 'client_id' => $tenant->client_id]
)]);

return Socialite::driver('okta')->redirect();

For cleaner isolation, use Socialite::buildProvider(\SocialiteProviders\Okta\Provider::class, $config) and skip the string-keyed driver entirely.

Group-based authorization. Request the groups scope (add it via ->setScopes([...]) or ->scopes([...])), configure a groups claim on the Okta authorization server, then read it from the raw payload:

$groups = $oktaUser->user['groups'] ?? [];
abort_unless(in_array('Admins', $groups), 403);

This is the most common reason teams reach for Okta instead of plain OIDC — use it, but cache or persist the groups rather than re-reading them on every request.

Integration with Fortify / Breeze / Jetstream. Do not fight the starter kit's Socialite wiring. Register okta as a socialite provider in config/services.php as above and point the existing Socialite::driver($provider) call at it. You will usually need to add an okta_id column and adapt the createUser callback in FortifyServiceProvider.

Refresh tokens. The provider gives you $oktaUser->token, $oktaUser->refreshToken, and $oktaUser->expiresIn. If you need to call Okta APIs on the user's behalf, persist these and refresh with a small service class rather than doing it inline in the callback.

Testing. Do not hit Okta in CI. Use Socialite::shouldReceive('driver->user')->andReturn($fakeUser) in feature tests, and unit-test your claims-to-user mapping separately. The provider itself rarely needs testing in your app.

Gotchas and Tips

Authorization server path mismatch is the #1 failure. The provider constructs URLs under /oauth2/v1/... (the Okta org authorization server). If your Okta tenant uses the default custom authorization server, the real endpoints are /oauth2/default/v1/.... Setting base_url to https://org.okta.com/oauth2/default will not fix this because the provider appends the path itself. You will need to subclass Provider and override getAuthUrl(), getTokenUrl(), and getUserByToken(), or use a package/version that exposes an authorization-server option. Verify this against the provider source before going to production — a mismatch produces a 404 on the Okta login page, which looks like a network problem but is not.

base_url formatting. Use the bare org URL with scheme and no trailing slash (https://dev-123456.okta.com). A trailing slash or missing scheme causes malformed URLs. The provider trims trailing slashes in some versions, but do not rely on it.

Redirect URI must match byte-for-byte. Okta compares the redirect_uri against the registered value exactly. http vs https, trailing slash, port, and www all matter. This is the second most common cause of redirect_uri mismatch errors.

InvalidStateException under load balancers. Socialite stores state in the session. If your app runs behind multiple nodes without a shared session store, users randomly fail the callback. Use Redis/database sessions, or configure sticky sessions.

Null name and nickname. The mapped name comes from the name claim, which is not guaranteed. preferred_username may also be absent depending on org settings. Always fall back to email when building your local user record, and do not assume name is populated.

groups claim gotchas. The claim is only present if you request the scope and the authorization server is configured to include it. Large group memberships can also push the ID token past header-size limits or Okta's token size cap — if you have users in hundreds of groups, filter the claim on the Okta side.

Do not trust the provider for token validation. This driver performs the code exchange and fetches the userinfo endpoint; it does not verify ID token signatures for you. If you are consuming the ID token elsewhere, validate it against Okta's JWKS.

Pin the version. 11 stars and a read-only split mean this is a low-traffic package. Pin a known-good version in composer.json, and if you need a fix, open the PR against SocialiteProviders/Providers — changes to this repository will not be merged.

Extension point. If you need to add query parameters or change scopes globally, subclass SocialiteProviders\Okta\Provider (it is a thin AbstractProvider) and register it with Socialite::extend('okta', ...) rather than forking. The provider class is deliberately small, so overriding one or two methods is usually cheaper than a fork.

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