oidc-hosted-page-laravel
SKILL.md
Implement SSOJet OIDC (PHP / Laravel)
This expert AI assistant guide walks you through integrating "Sign in with SSO" functionality into an existing login page in a Laravel application using SSOJet as an OIDC identity provider.
1. Prerequisites
- An existing Laravel 10+ application with a login page.
- PHP 8.1+ and Composer.
- An active SSOJet account.
- SSO Connection Setup Guide
- Required package:
laravel/socialite.
2. Implementation Steps
Step 1: Create Application in SSOJet
- Log in to the SSOJet Dashboard.
- Navigate to Applications.
- Create a new application (e.g., "MyLaravelApp", type Regular Web App).
- Configure the callback URI (e.g.,
http://localhost:8000/auth/callback). - Retrieve Client ID and Client Secret.
- Copy the Issuer URL from the Advanced > Endpoints section.
Step 2: Modify the Existing Laravel Project
Substep 2.1: Install Dependencies
composer require laravel/socialite
Substep 2.2: Configure Environment Variables
Add to your .env file:
SSOJET_ISSUER_URL=https://auth.ssojet.com
SSOJET_CLIENT_ID=your_client_id
SSOJET_CLIENT_SECRET=your_client_secret
SSOJET_REDIRECT_URI=http://localhost:8000/auth/callback
Add to config/services.php:
'ssojet' => [
'issuer_url' => env('SSOJET_ISSUER_URL'),
'client_id' => env('SSOJET_CLIENT_ID'),
'client_secret' => env('SSOJET_CLIENT_SECRET'),
'redirect' => env('SSOJET_REDIRECT_URI'),
],
Substep 2.3: Create SSOJet Socialite Provider
<?php
// app/Providers/SSOJetProvider.php
namespace App\Providers;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\User;
class SSOJetProvider extends AbstractProvider
{
protected $scopes = ['openid', 'profile', 'email'];
protected $scopeSeparator = ' ';
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase(
config('services.ssojet.issuer_url') . '/oauth2/authorize', $state
);
}
protected function getTokenUrl()
{
return config('services.ssojet.issuer_url') . '/oauth2/token';
}
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get(
config('services.ssojet.issuer_url') . '/oauth2/userinfo',
['headers' => ['Authorization' => 'Bearer ' . $token]]
);
return json_decode($response->getBody(), true);
}
protected function mapUserToObject(array $user)
{
return (new User())->setRaw($user)->map([
'id' => $user['sub'] ?? null,
'name' => $user['name'] ?? null,
'email' => $user['email'] ?? null,
]);
}
}
Register in AppServiceProvider.php:
use Laravel\Socialite\Facades\Socialite;
use App\Providers\SSOJetProvider;
public function boot(): void
{
Socialite::extend('ssojet', function ($app) {
$config = $app['config']['services.ssojet'];
return new SSOJetProvider($app['request'], $config['client_id'], $config['client_secret'], $config['redirect']);
});
}
Substep 2.4: Update Login Page/UI
Modify resources/views/auth/login.blade.php:
<div class="login-container">
<h1>Sign In</h1>
<form id="loginForm" method="POST" action="{{ route('login') }}">
@csrf
<div>
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
</div>
<div id="passwordField">
<label for="password">Password</label>
<input type="password" id="password" name="password" required />
</div>
<input type="hidden" id="isSSO" name="is_sso" value="false" />
<button type="submit" id="submitBtn">Sign In</button>
</form>
<button type="button" onclick="toggleSSO()">Sign in with SSO</button>
</div>
<script>
function toggleSSO() {
const f = document.getElementById('isSSO');
const p = document.getElementById('passwordField');
const b = document.getElementById('submitBtn');
if (f.value === 'false') {
f.value = 'true'; p.style.display = 'none';
document.getElementById('password').removeAttribute('required');
b.textContent = 'Continue with SSO';
} else {
f.value = 'false'; p.style.display = 'block';
document.getElementById('password').setAttribute('required','true');
b.textContent = 'Sign In';
}
}
</script>
Substep 2.5: Update Backend Logic
SSO Controller (app/Http/Controllers/SSOController.php):
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
class SSOController extends Controller
{
public function login(Request $request)
{
if ($request->input('is_sso') === 'true') {
return Socialite::driver('ssojet')
->with(['login_hint' => $request->input('email')])
->redirect();
}
// Existing password login logic
$credentials = $request->validate(['email' => 'required|email', 'password' => 'required']);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect('/dashboard');
}
return back()->withErrors(['email' => 'Invalid credentials.']);
}
public function callback(Request $request)
{
try {
$ssojetUser = Socialite::driver('ssojet')->user();
$user = User::updateOrCreate(
['email' => $ssojetUser->getEmail()],
['name' => $ssojetUser->getName(), 'ssojet_id' => $ssojetUser->getId()]
);
Auth::login($user);
return redirect('/dashboard');
} catch (\Exception $e) {
\Log::error('OIDC Callback Error: ' . $e->getMessage());
return redirect('/login')->withErrors(['sso' => 'SSO authentication failed.']);
}
}
}
Routes (routes/web.php):
use App\Http\Controllers\SSOController;
Route::get('/login', fn() => view('auth.login'))->name('login');
Route::post('/login', [SSOController::class, 'login']);
Route::get('/auth/callback', [SSOController::class, 'callback']);
Step 3: Test the Modified Connection
- Start your application:
php artisan serve. - Navigate to
http://localhost:8000/login. - Click "Sign in with SSO", enter a test email, and submit.
- You should be redirected to SSOJet, then back to
/dashboard.
3. Additional Considerations
- Security: Never commit
.envto source control. - Database: Add a
ssojet_idcolumn to theuserstable via migration. - Styling: Adapt the Blade templates to match your design system.
4. Support
- Contact SSOJet support: Reach out if you have integration questions.
- Library Documentation: Refer to the Laravel Socialite documentation.
Weekly Installs
2
Repository
ssojet/skillsGitHub Stars
3
First Seen
14 days ago
Security Audits
Installed on
opencode2
gemini-cli2
codebuddy2
github-copilot2
codex2
kimi-cli2