Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mahdipak's avatar

Best Practice for Syncing Users & SSO Between Two Laravel Apps Using Sanctum

Hi everyone,

I’m working on a setup where I have two distinct Laravel applications:

Main App – handles user registration/login via mobile (OTP or password)

LMS App – a separate education platform that needs the same user profiles

All user registration and authentication happens in the Main App. Whenever a user:

Enters their phone number

Receives (and verifies) an OTP if they’re new

Completes their profile (first name, last name, email, gender, media files, etc.)

…they should automatically be mirrored into the LMS database with all the same fields.

0 likes
1 reply
martinbean's avatar

@mahdipak Install Passport in the “main” app. Create an OAuth client for your LMS app. “Logging in” to the LMS is then a case of being redirected to the main app to authorise the request.

When the user is redirected back to the LMS with an OAuth access token, you should use that token to fetch the user’s details from an endpoint, to create or update the user in your LMS app’s database, and then authorise them. Something like:

class AuthController extends Controller
{
    public function handleProviderCallback()
    {
        // Get user details from main app using OAuth token
        $user = Socialite::driver('your_app')->user();

        // Create/update user in LMS database
        $lmsUser = User::query()->updateOrCreate(
            attributes: [
                'external_id' => $user->getId(),
            ],
            values: [
                'name' => $user->getName(),
            ],
        );

        // Authenticate user
        Auth::login($lmsUser);

        // Redirect user to where they need to be
        return redirect()->intended('/');
    }

This is assuming your users table only has the following schema:

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('external_id')->unique();
    $table->string('name');
    $table->timestamps();
});

Because any other fields (email, password, etc) are redundant, given you’re not authenticating them in the LMS using an email and password.

You’d also need to create your own Socialite provider, but they’re pretty easy as they’re essentially just classes that have a handful of methods to return URLs (such as the access token URL, and the URL to retrieve user information from). In a service provider, you’d register a Socialite extension by doing something like:

Socialite::extend('your_app', fn () => new YourAppSocialiteProvider(
    request: $this->app->make('request'),
    clientId: $this->app->make('config')->get('services.your_app.client_id'),
    clientSecret: $this->app->make('config')->get('services.your_app.client_secret'),
    redirectUrl: $this->app->make('url')->to('/auth/your-app/callback'),
));
use Laravel\Socialite\Two\AbstractProvider;

class YourAppSocialiteProvider extends AbstractProvider
{
    // Implement abstract methods here...
}

Please or to participate in this conversation.