ums-lspl/sso-client

Laravel client package for SmartExam SSO — verify tokens and authenticate users in consumer apps.

Maintainers

Package info

github.com/rajkumarchanda/ums-sso-client

pkg:composer/ums-lspl/sso-client

Transparency log

Statistics

Installs: 43

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

2.0.0 2026-07-22 07:25 UTC

This package is auto-updated.

Last update: 2026-07-22 07:27:58 UTC


README

Laravel package for consumer apps that sign users in with SmartExam SSO.

SmartExam issues a signed token after the user approves login. This package verifies the token, creates or updates a local user, and starts a Laravel session.

Requirements: PHP 8.1+, Laravel 9–13, and an SSO application in SmartExam Admin → SSO → Applications.

Version 2.x — active development on main. For Laravel 7–8 / PHP 7.2+, use the 1.x branch (composer require ums-lspl/sso-client:^1.0).

Quick start

1. Install

composer require ums-lspl/sso-client:^2.0
php artisan smartexam-sso:install --migrate

This publishes the config and migration, runs migrations, then diagnoses your setup. It adds a nullable, unique smartexam_id column to users.

Equivalent manual steps:

php artisan vendor:publish --tag=smartexam-sso-config
php artisan vendor:publish --tag=smartexam-sso-migrations
php artisan migrate
php artisan smartexam-sso:diagnose

2. Configure .env

SMARTEXAM_URL=https://your-ums-server.example.com
SSO_CLIENT_KEY=your-client-key
SSO_CLIENT_SECRET=your-client-secret
SSO_CALLBACK_URL=https://your-app.example.com/sso/callback
SSO_AFTER_LOGIN_REDIRECT=/dashboard
SSO_REMEMBER_LOGIN=false

Register the same SSO_CALLBACK_URL in SmartExam Admin for your client key.

3. Update your User model

protected $fillable = [
    // ...
    'smartexam_id',
];

4. Add SSO to your login page

In your auth layout <head>:

<meta name="csrf-token" content="{{ csrf_token() }}">

In the layout body (no publish step needed):

@include('smartexam-sso::login-script')

On your login button:

<button type="button" onclick="signInWithSmartExam()">Sign in with SmartExam</button>

That’s it. The partial loads the SmartExam overlay, stores CSRF state, opens the popup, and POSTs to the exchange route.

How it works

sequenceDiagram
    participant Browser
    participant App as Your Laravel app
    participant UMS as SmartExam

    Browser->>App: Open login page
    Browser->>UMS: Popup — user approves SSO
    UMS->>Browser: Redirect popup to /sso/callback
    Browser->>App: POST /api/sso/exchange
    App->>App: Verify token, login user
    Browser->>App: Redirect to dashboard
Loading

Recommended: popup + exchange (POST /api/sso/exchange) — handled by @include('smartexam-sso::login-script'). Tokens stay out of top-level browser history.

Alternative: full browser redirect to GET /sso/callback (tokens appear in the URL). Disable with SMARTEXAM_SSO_ALLOW_REDIRECT_CALLBACK=false if you only want overlay exchange.

UMS dashboard launch: when users open your app from Connected Apps on the SmartExam dashboard, SmartExam calls GET /sso/launch/{client} and redirects to your callback with source=issuer. No extra route is needed in this package — the existing GET /sso/callback handles it. Ensure:

  • SMARTEXAM_SSO_ALLOW_REDIRECT_CALLBACK=true (default)
  • SMARTEXAM_SSO_ALLOW_ISSUER_LAUNCH=true (default)
  • SMARTEXAM_SSO_REQUIRE_STATE=true is fine — issuer launches skip state when source=issuer is present
  • Optional landing query param (from SmartExam Login Landing URL) overrides SSO_AFTER_LOGIN_REDIRECT after login

Artisan commands

Command Description
php artisan smartexam-sso:install Publish config + migrations, then diagnose
php artisan smartexam-sso:install --migrate Also run migrations
php artisan smartexam-sso:install --force Overwrite previously published files
php artisan smartexam-sso:install --no-diagnose Publish only
php artisan smartexam-sso:diagnose Check env, routes, user model, and smartexam_id
php artisan smartexam-sso:diagnose --ping Also HTTP-check SmartExam /js/sso-overlay.js

Publish tags

Tag Use when
smartexam-sso-config You need to customize routes, provisioner, etc.
smartexam-sso-migrations First install — adds smartexam_id
smartexam-sso-views You want to edit the login script
Views are optional. To customize the login script:
php artisan vendor:publish --tag=smartexam-sso-views
@include('vendor.smartexam-sso.login-script')

Environment variables

Variable Required Description
SMARTEXAM_URL Yes SmartExam server URL (must match token iss)
SSO_CLIENT_KEY Yes Client key from SmartExam Admin
SSO_CLIENT_SECRET Yes Secret used to verify token signatures
SSO_CALLBACK_URL Yes Your callback URL (must match SmartExam registration)
SSO_AFTER_LOGIN_REDIRECT No Where to go after login (relative path preferred). Default: /
SSO_AUDIENCE No Token aud claim. Default: origin of SSO_CALLBACK_URL
SSO_REMEMBER_LOGIN No Laravel “remember me” after SSO. Default: false
SMARTEXAM_SSO_ROUTES No Enable package routes. Default: true
SMARTEXAM_SSO_ROUTE_PREFIX No Prefix for SSO routes. Default: empty
SMARTEXAM_SSO_REQUIRE_STATE No Require session state. Default: true
SMARTEXAM_SSO_ALLOW_ISSUER_LAUNCH No Accept UMS dashboard launch (source=issuer) without state. Default: true
SMARTEXAM_SSO_THROTTLE No Rate limit maxAttempts,decayMinutes. Default: 20,1
SMARTEXAM_SSO_CLOCK_SKEW No Allowed iat/exp skew in seconds. Default: 60
SMARTEXAM_SSO_REPLAY_PROTECTION No Reject reused tokens. Default: true
SMARTEXAM_SSO_ALLOW_REDIRECT_CALLBACK No Allow top-level GET callback login. Default: true
SMARTEXAM_SSO_GENERIC_ERRORS No Hide detailed errors from browsers. Default: true in production
SMARTEXAM_SSO_REQUIRE_HTTPS No Fail diagnose if issuer/callback use http in production. Default: true

Routes

Registered automatically (customize in config/smartexam-sso.php):

Method Path Name
GET /sso/callback smartexam-sso.callback
POST /api/sso/exchange smartexam-sso.exchange
POST /sso/logout smartexam-sso.logout

All SSO routes are rate-limited (SMARTEXAM_SSO_THROTTLE, default 20,1).

Security features

Feature Behaviour
Replay protection Each token can be exchanged once (cached until exp)
Rate limiting Throttle on callback + exchange
Clock skew / iat Rejects future iat and expired exp with configurable skew
Base64url Accepts standard base64 and base64url payloads
Safe redirect SSO_AFTER_LOGIN_REDIRECT must be relative or same-host
Generic errors Production browsers get SSO login failed. (details in logs)
Session binding Stores issuer session_id in the local session
HTTPS assert smartexam-sso:diagnose fails on http:// URLs in production
Overlay preference Prefer resolveOnly + exchange so tokens are not left in the address bar

Local logout

<form method="POST" action="{{ route('smartexam-sso.logout') }}">
    @csrf
    <button type="submit">Log out</button>
</form>

{{-- Also send the user to SmartExam sign-in --}}
<form method="POST" action="{{ route('smartexam-sso.logout', ['issuer' => 1]) }}">
    @csrf
    <button type="submit">Log out everywhere</button>
</form>
use SmartExam\SsoClient\Services\SsoAuthenticationService;

app(SsoAuthenticationService::class)->boundIssuerSessionId(); // issuer session_id if present

Customization

Custom user provisioning

Default behavior: find or create user by email, set smartexam_id from token sub.

For custom logic, implement SmartExam\SsoClient\Contracts\SsoUserProvisioner:

// config/smartexam-sso.php
'user_provisioner' => App\Services\YourSsoUserProvisioner::class,

Post-login hook

use SmartExam\SsoClient\Events\SmartExamSsoAuthenticated;

Event::listen(SmartExamSsoAuthenticated::class, function ($event) {
    // $event->user, $event->payload
});

URL helpers

use SmartExam\SsoClient\Support\SsoUrl;
use SmartExam\SsoClient\Support\SafeRedirect;

SsoUrl::overlayScript();      // SmartExam /js/sso-overlay.js URL
SsoUrl::callbackUrl();        // Host-aware redirectUrl for the overlay
SsoUrl::connect($state);      // Full-page SSO connect URL
SsoUrl::issuerSignIn();       // SmartExam sign-in page
SafeRedirect::afterLogin();   // Safe post-login path

Troubleshooting

Error Fix
Unexpected token audience Set SSO_AUDIENCE to match your app Base URL
Unexpected token issuer SMARTEXAM_URL must match token issuer
SSO token has already been used Token replay — start a new SSO login
Invalid / missing SSO state Use @include('smartexam-sso::login-script') or reload login page
CSRF token missing Add <meta name="csrf-token"> to layout
SSO client secret is not configured Set SSO_CLIENT_SECRET, run php artisan config:clear
Too Many Attempts Raise SMARTEXAM_SSO_THROTTLE or wait for the window to reset

Testing

composer test

License

MIT