unimontes-cead/sso-client
Composer 安装命令:
composer require unimontes-cead/sso-client
包简介
Socialite driver and client-app integration helpers for the UNIMONTES CEAD SSO.
README 文档
README
Laravel Socialite driver + login glue for applications that authenticate through the UNIMONTES CEAD SSO (a Laravel Passport authorization server).
What this package does
- Registers a
ssoSocialite driver against the SSO's own OAuth2 endpoints (/oauth/authorize,/oauth/token,/api/user) — no manualconfig/services.phpentry needed. - Exposes the data returned by the SSO as a typed
SsoUserDTO (id,name,email,cpf,phone,avatarUrl,roles) instead of a generic array. Every field butidis nullable: the SSO omits a field entirely when this client wasn't granted the matching scope, sonullmeans "not authorized to see this", not "empty". rolesis an array ofSsoUserRole(name,value,startDate,endDate) — every role the user currently holds on the SSO (a user can hold more than one at once, each with its own date range).valueis the SSO's internal role ID, stable across relabeling, so it's the safer thing to persist if you want to correlate SSO roles against your own local roles — or just use it directly as your local role.SsoUser::hasRole(int $value): boolis a shortcut for checking membership.- Defines
Contracts\SsoAuthenticatable, an interface your ownUsermodel implements to say how SSO data maps to a local user. - Optionally registers ready-made
GET {prefix}/redirect,GET {prefix}/callback, andPOST {prefix}/logoutroutes that do the full login/logout round-trip for you.
Scopes are the SSO's decision, not this app's
The driver always requests every scope the SSO knows about
(name,email,cpf,phone,avatar,role) — there's no SSO_SCOPES env var to
configure here. That's intentional: the SSO's ScopeRepository clips
whatever's requested down to whatever an admin actually granted this
client on the SSO's own "Aplicações" screen, regardless of what's asked
for. So requesting everything unconditionally is safe — you only ever get
back what the SSO already decided this client is allowed to see — and it
means scope configuration lives in exactly one place (the SSO), not
duplicated into every client's .env.
Installation
composer require unimontes-cead/sso-client composer require laravel/socialite
Laravel's package auto-discovery registers SsoClientServiceProvider
automatically — no manual entry in bootstrap/providers.php needed.
Configuration
Publish the config file:
php artisan vendor:publish --tag=sso-config
Set these in .env (get SSO_CLIENT_ID/SSO_CLIENT_SECRET from an admin
on the SSO's "Aplicações" screen — its "URL inicial" doesn't need to point
here, but its registered redirect URIs must include your callback URL):
SSO_BASE_URL=https://sso.unimontes.example SSO_CLIENT_ID= SSO_CLIENT_SECRET= # Only needed if you disable the built-in routes below and drive # Socialite yourself with a different callback path. # SSO_REDIRECT_URI=https://your-app.example/auth/sso/callback SSO_ROUTES_ENABLED=true SSO_USER_MODEL=App\Models\User
Implementing the contract
Your App\Models\User must implement SsoAuthenticatable::fromSsoData() —
it receives the SsoUser DTO and returns the local user to log in as,
typically an updateOrCreate() keyed on the SSO's id:
use UnimontesCead\SsoClient\Contracts\SsoAuthenticatable; use UnimontesCead\SsoClient\SsoUser; class User extends Authenticatable implements SsoAuthenticatable { public static function fromSsoData(SsoUser $ssoUser): static { return static::updateOrCreate( ['sso_id' => $ssoUser->id], [ 'name' => $ssoUser->name, 'email' => $ssoUser->email, 'cpf' => $ssoUser->cpf, 'phone' => $ssoUser->phone, 'avatar_url' => $ssoUser->avatarUrl, ], ); } }
You'll need a sso_id column (string/uuid, unique) on your users table to
key that lookup on.
Using roles
$ssoUser->roles is null when this client wasn't granted the role
scope, otherwise an array of SsoUserRole. A common pattern is to store the
active roles' values directly as your local roles, since the SSO already
manages date-ranged role assignment for you:
$roleValues = $ssoUser->roles !== null ? array_map(fn (SsoUserRole $role) => $role->value, $ssoUser->roles) : []; $user->roles()->sync($roleValues); // or a quick membership check, e.g. gating admin-only UI: if ($ssoUser->hasRole(1)) { /* ... */ }
Logging in
With the built-in routes (default), just link to the redirect route:
<a href="{{ route('sso.redirect') }}">Entrar com o SSO</a>
That's the whole flow — it exchanges the code, fetches /api/user, calls
your User::fromSsoData(), logs the user in, and redirects to
sso.routes.redirect_after_login.
Logging out
<form method="POST" action="{{ route('sso.logout') }}"> @csrf <button type="submit">Sair</button> </form>
This ends the local session and redirects the browser to the SSO's own
single-logout endpoint (GET /oauth/logout/{client_id} on the SSO), which
ends the SSO's session and revokes every OAuth token this user has been
issued, then bounces back to this client's registered "URL inicial".
What this does and doesn't do: the SSO won't silently re-authenticate the user anymore, so the next "entrar com o SSO" — in this app or any other — requires fresh credentials. It does not reach into other client apps' already-open local sessions and close them; that would require a back-channel logout protocol (each client exposing its own logout webhook that the SSO calls server-to-server) which this package doesn't implement. For most internal tooling, killing the SSO session is the meaningful "logout everywhere" boundary — treat true simultaneous multi-tab/multi-app session termination as a separate, bigger feature if you need it.
Rolling your own flow
Set SSO_ROUTES_ENABLED=false and drive it yourself:
use Laravel\Socialite\Facades\Socialite; Route::get('/login/sso', fn () => Socialite::driver('sso')->redirect()); Route::get('/login/sso/callback', function () { $ssoUser = Socialite::driver('sso')->user(); // SsoUser instance $user = \App\Models\User::fromSsoData($ssoUser); auth()->login($user, remember: true); return redirect('/'); }); Route::post('/logout/sso', function (\Illuminate\Http\Request $request) { auth()->guard('web')->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect()->away( rtrim(config('sso.base_url'), '/').'/oauth/logout/'.config('sso.client_id'), ); });
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-10