curl eID /api/public/government-services?excludeClientId={WSO2_CLIENT_ID} — tiles after admin approval
Generic copy-paste steps using placeholder client credentials. After onboarding, open your application in the RP portal for guides pre-filled with your client ID and redirect URIs.
Step 1
Architecture overview
Citizens sign in through the SXM Identity Broker, which federates to the national eID UI. Your Laravel app is the OAuth client — it never collects eID passwords. After callback, exchange the code for tokens, call broker UserInfo with the access_token, merge claims, and create a local session.
text
Browser → /login (PKCE + state)
→ Broker authorize (https://localhost:9443/oauth2/authorize)
→ SXM eID login + MFA
→ GET https://my-portal.gov.sx/auth/callback?code=...&state=...
→ POST https://localhost:9443/oauth2/token (code + code_verifier + client_secret)
→ GET https://localhost:9443/oauth2/userinfo (Bearer access_token)
→ User::updateOrCreate by sub (eid, citizen_status, rp_token, profile)
→ Auth::login($user)
Step 2
Configure .env
Paste into project root .env. Use your one-time credential link for the client secret. Local example redirect: http://coci.test/auth/callback
env
# My Government Portal — SXM Identity Broker
WSO2_BASE_URL=https://localhost:9443
WSO2_CLIENT_ID=YOUR_CLIENT_ID
WSO2_CLIENT_SECRET=YOUR_CLIENT_SECRET
WSO2_REDIRECT_URI=https://my-portal.gov.sx/auth/callback
WSO2_SCOPE="openid profile email eid"
WSO2_AUTHORIZE_URL=https://localhost:9443/oauth2/authorize
WSO2_TOKEN_URL=https://localhost:9443/oauth2/token
WSO2_USERINFO_URL=https://localhost:9443/oauth2/userinfo
WSO2_LOGOUT_URL=https://localhost:9443/oidc/logout
WSO2_POST_LOGOUT_REDIRECT_URI=https://my-portal.gov.sx/
# Auth prompt only: login | none — never set consent (broker owns consent)
WSO2_OAUTH_PROMPT=login
# When callback has no ?code= (user cancelled at broker)
EID_FRONTEND_URL=http://localhost:3000
# Local debug only (log or dump claims on callback): WSO2_DEBUG_CLAIMS=log
Step 3
Wire config/services.php
Add the wso2 and eid blocks so your controller reads broker settings from the environment.
Use the broker access_token (opaque UUID on WSO2). Do not call eID /connect/userinfo with this token. Merge id_token + UserInfo so eid-scope fields are not dropped.
Redirect URI for RP-EXAMPLE-0001 must exactly match WSO2_REDIRECT_URI. See Claims doc if eid / rp_token are missing after login.
shell
# 1. Refresh config
php artisan config:clear
# 2. Run app (Herd: https://my-government-portal.test — or php artisan serve)
# 3. Browser: open /login
# Flow: Laravel → broker → eID → https://my-portal.gov.sx/auth/callback → /dashboard
# 4. Optional: call UserInfo with access_token from token response
curl -sS -H "Authorization: Bearer {broker_access_token}" \
https://localhost:9443/oauth2/userinfo
# 5. Registered redirect URI (must match exactly):
https://my-portal.gov.sx/auth/callback
Step 12
Portal switcher — .env (eID catalog)
Add alongside your WSO2 variables. EID_API_BASE_URL must reach GET /api/public/government-services from your Laravel server.
env
# Government service launcher (dynamic catalog from eID)
EID_API_BASE_URL=http://localhost:5026
EID_FRONTEND_URL=http://localhost:3000
EID_CITIZEN_PORTAL_PATH=/citizen/profile
GOVERNMENT_PORTAL_ID=my-rp
Step 13
Portal switcher — config (services + fallback)
Extend config/services.php and add config/government_portals.php for local identity + offline fallback tiles.
Register in AppServiceProvider. Use <x-portal-switcher /> in your authenticated layout (full UI: copy COCI resources/views/components/portal-switcher.blade.php).