Demo credentials + SCIM provisioning
How the student@comptech.com user gets provisioned via WSO2 IS's SCIM2 API, a single /credentials.html page that's the source of truth for every demo login, and one workaround for the SCIM/admin-console permission gap. Companion commit bf2e1e35 in the insurance-app repo.
Two portals, both gated by OIDC against WSO2 IS, both expecting a real human user to log in. Up to this point the curriculum has been silent on which user — every “Verify” section ended with “open in a browser” and waved at credentials. This chapter fills the gap.
The deliverable is two things: a script-driven SCIM provisioning
of one demo user (student@comptech.com / Student@1234) and a single
/credentials.html page hosted by Liberty that lists every login the
demo exposes. The whole thing is ~35 minutes of work and exists
because handing a fresh student “the credentials” turned out to be a
multi-page email otherwise.
Companion commit: bf2e1e35 in insurance-app.
SCIM2 — provision a user without the IS console
WSO2 IS exposes a SCIM2 API at /scim2/Users. It accepts a standard
SCIM JSON payload and creates a user under the primary userstore in
one POST. Compared to clicking through Console → User Management →
Add User, it’s:
- Idempotent (with a delete-then-create wrapper if needed).
- Scriptable for the SETUP.md runbook.
- Auditable as a single line in version control rather than five console clicks no one will reproduce.
curl -k -sS -X POST -u admin:admin \
https://localhost:9444/scim2/Users \
-H 'Content-Type: application/scim+json' \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "student@comptech.com",
"password": "Student@1234",
"emails": [{ "primary": true, "value": "student@comptech.com" }],
"name": { "givenName": "Demo", "familyName": "Student" }
}' | jq .
The response includes the user’s id (a UUID). Save it; later steps
need it to add the user to the admin role and the admin Group.
Role + Group assignment
A bare SCIM-created user can log into the customer portal and the agent dashboard but cannot open the WSO2 admin consoles (IS Console / Carbon, APIM Publisher / Devportal / Admin). The permission model splits “can-authenticate” from “can-administer.” To get partial admin access:
USER_ID=<from previous SCIM POST>
# 1) Add to the organization-level admin role
curl -k -sS -X PATCH -u admin:admin \
https://localhost:9444/scim2/Roles/{admin-role-id} \
-H 'Content-Type: application/scim+json' \
-d "{
\"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],
\"Operations\":[{
\"op\":\"add\",
\"path\":\"users\",
\"value\":[{\"value\":\"$USER_ID\"}]
}]
}"
# 2) Add to the admin Group (carries Administrator application role)
curl -k -sS -X PATCH -u admin:admin \
https://localhost:9444/scim2/Groups/{admin-group-id} \
-H 'Content-Type: application/scim+json' \
-d "{
\"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],
\"Operations\":[{
\"op\":\"add\",
\"path\":\"members\",
\"value\":[{\"value\":\"$USER_ID\"}]
}]
}"
Now student@comptech.com can also reach My Account
(https://is.insurance-app.comptech-lab.com/myaccount) and change its
own profile. The IS Console + APIM admin consoles still reject it.
The gap: SCIM-created admins can’t open admin consoles
This is the workaround-worth-knowing-about. WSO2 IS Console and APIM
Publisher / Devportal / Admin all key their access checks against
Carbon-internal role memberships that SCIM2 does not currently expose
through /scim2/Users or /scim2/Groups. A user created entirely via
SCIM — even one added to every role SCIM can see — still gets a 403
when they try /console or /publisher.
Two real options, both deferred to a future slice:
- Federate APIM with IS as a key manager so the APIM admin consoles consume IS users directly.
- Add Carbon-internal admin role membership via the SOAP UserAdmin
API (
/services/UserAdmin?wsdl). It’s the legacy interface that predates SCIM2; it can write the role tables the new admin consoles read.
For the demo, the workaround is the one documented on the credentials
page: use admin/admin for the WSO2 admin consoles, use
student@comptech.com for everything customer-facing. Two logins,
clearly labeled, no surprise 403s for the student.
The /credentials.html page
The Liberty webapp gains a tenth static page that lists every login
the demo exposes — one per surface, with the actual URL and the
credentials inline. It’s a single HTML file, served from
src/main/webapp/credentials.html alongside the other tour pages.
The structure mirrors the audiences:
| Section | Who it’s for | Credentials |
|---|---|---|
| Portal user | The customer + agent portals (real OIDC) | student@comptech.com / Student@1234 |
| WSO2 admin | IS Console, Carbon, APIM Publisher / Devportal / Admin | admin / admin |
| Object storage | MinIO console | minioadmin / minioadmin |
| SigNoz | First-launch setup; no credentials | (set on first signin) |
| Other | Adminer, Kafka UI, RedisInsight, Mailpit | no auth (lab is intentionally permissive) |
Each row has the canonical URL hyperlinked and a short note about what the surface is for. The “intentionally permissive” callout matters — students often poke at things and the lab WANTS them to. Do not run this configuration anywhere real.
The nav of /index.html gains a Credentials link so the page is
one click from the tour landing, and the live-portals callout on the
home page now points students at the credentials sheet before they
ever try to sign in.
Verify
# SCIM provisioning is in place — the user exists
curl -k -sS -u admin:admin \
'https://localhost:9444/scim2/Users?filter=userName+eq+student@comptech.com' \
| jq '.Resources[0].userName'
# "student@comptech.com"
# The customer portal accepts the user via OIDC
# (manual: click "Sign in" on https://my.insurance-app.comptech-lab.com,
# enter student@comptech.com / Student@1234, land back signed in)
# /credentials.html is served and reachable
curl -sI https://app.insurance-app.comptech-lab.com/credentials.html | head -1
# HTTP/2 200
The page is the single artifact you hand to a student. Bookmark it, print it, embed it in onboarding — it’s the URL that ends every “how do I sign into X?” question.
What you have
- A scripted SCIM2 provisioning of one demo user, added to the admin role + admin Group.
- A documented workaround for the SCIM/admin-console permission gap
(use
admin/adminfor the WSO2 admin surfaces). - A single
/credentials.htmlpage that’s the source of truth for every demo login. - Honest documentation that the lab is intentionally permissive — the credentials are demo-grade, not production-grade.
One more cross-cutting chapter on hardening the earlier slices and the track is done.