Read legacy SSO config
GET/api/auth/sso/config
Authentication: bearer token.
Permission: settings.sso.
curl -X GET "https://shellius.example.com/api/auth/sso/config" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Upsert legacy SSO config
PUT/api/auth/sso/config
Authentication: bearer token.
Permission: settings.sso.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
provider | string | Yes | One of oidc, saml. |
presetId | string | No | One of google, entra, okta, auth0, generic-oidc, saml. |
clientId | string | Yes | 1–500 characters. |
clientSecret | string | No | 1–2000 characters. |
issuerUrl | string | Yes | |
redirectUri | string | No | |
scopes | string | No | At most 500 characters. |
isActive | boolean | No | |
defaultRole | string | No | At most 100 characters. |
defaultGroupId | string | No | May be null. |
autoProvision | boolean | No | |
allowedDomains | array | No | At most 50. |
requireVerifiedEmail | boolean | No | |
tenantId | string | No | |
oktaDomain | string | No | |
auth0Domain | string | No |
curl -X PUT "https://shellius.example.com/api/auth/sso/config" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "oidc",
"clientId": "…",
"issuerUrl": "…"
}'200 OK
{ "success": true, "data": { … } }Test legacy SSO config
POST/api/auth/sso/config/test
Authentication: bearer token.
Permission: settings.sso.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
provider | string | No | One of oidc, saml. |
issuerUrl | string | No |
curl -X POST "https://shellius.example.com/api/auth/sso/config/test" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "oidc",
"issuerUrl": "…"
}'200 OK
{ "success": true, "data": { … } }List SSO providers
GET/api/auth/sso/providers
Revision 2 — GET/POST/PATCH/DELETE /api/auth/sso/providers.
Authentication: bearer token.
Permission: settings.sso.
curl -X GET "https://shellius.example.com/api/auth/sso/providers" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Create SSO provider
POST/api/auth/sso/providers
Authentication: bearer token.
Permission: settings.sso.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
name | string | Yes | 1–120 characters. |
presetId | string | Yes | |
clientId | string | Yes | 1–500 characters. |
clientSecret | string | No | 1–2000 characters. |
issuerUrl | string | No | |
scopes | string | No | At most 500 characters. |
defaultRole | string | Yes | At most 100 characters. |
defaultGroupId | string | No | May be null. |
autoProvision | boolean | Yes | |
allowedDomains | array | Yes | At most 50. |
allowedOrgs | array | No | Default []. 1–100. |
requireVerifiedEmail | boolean | Yes | |
isActive | boolean | Yes |
curl -X POST "https://shellius.example.com/api/auth/sso/providers" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "…",
"presetId": "…",
"clientId": "…",
"defaultRole": "…",
"autoProvision": false,
"allowedDomains": [],
"requireVerifiedEmail": false,
"isActive": false
}'201 Created
{ "success": true, "data": { … } }Test unsaved provider draft
POST/api/auth/sso/providers/test
Unsaved draft test. MUST be registered before /providers/:id/test so Express doesn't treat "test" as an :id.
Authentication: bearer token.
Permission: settings.sso.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
presetId | string | No | |
issuerUrl | string | No |
curl -X POST "https://shellius.example.com/api/auth/sso/providers/test" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"presetId": "…",
"issuerUrl": "…"
}'200 OK
{ "success": true, "data": { … } }Reorder providers
PUT/api/auth/sso/providers/order
Authentication: bearer token.
Permission: settings.sso.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
ids | array | Yes | At least 1. |
curl -X PUT "https://shellius.example.com/api/auth/sso/providers/order" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ids": []
}'200 OK
{ "success": true, "data": { … } }Test saved provider
POST/api/auth/sso/providers/:id/test
Authentication: bearer token.
Permission: settings.sso.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
curl -X POST "https://shellius.example.com/api/auth/sso/providers/{id}/test" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Update provider
PATCH/api/auth/sso/providers/:id
Authentication: bearer token.
Permission: settings.sso.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
name | string | No | 1–120 characters. |
presetId | string | No | |
clientId | string | No | 1–500 characters. |
clientSecret | string | No | At most 2000 characters. |
issuerUrl | string | No | |
scopes | string | No | At most 500 characters. |
defaultRole | string | No | At most 100 characters. |
defaultGroupId | string | No | May be null. |
autoProvision | boolean | No | |
allowedDomains | array | No | At most 50. |
allowedOrgs | array | No | 1–100. |
requireVerifiedEmail | boolean | No | |
isActive | boolean | No |
curl -X PATCH "https://shellius.example.com/api/auth/sso/providers/{id}" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "…",
"presetId": "…",
"clientId": "…"
}'200 OK
{ "success": true, "data": { … } }Delete provider
DELETE/api/auth/sso/providers/:id
Authentication: bearer token.
Permission: settings.sso.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
force | — | No |
curl -X DELETE "https://shellius.example.com/api/auth/sso/providers/{id}" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Public SSO summary for login page
GET/api/auth/sso/public-status
Authentication: none.
curl -X GET "https://shellius.example.com/api/auth/sso/public-status"200 OK
{ "success": true, "data": { … } }Trade one-time SSO callback code for session
POST/api/auth/sso/exchange
Public; trades a one-time callback code for a login-shaped response (so MFA applies uniformly to SSO sign-ins). MUST be registered before /:orgSlug (different HTTP method, but kept here for readability).
Authentication: none.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
code | string | Yes |
curl -X POST "https://shellius.example.com/api/auth/sso/exchange" \
-H "Content-Type: application/json" \
-d '{
"code": "…"
}'200 OK
{ "success": true, "data": { … } }OIDC/GitHub callback
GET/api/auth/sso/callback
No-orgSlug callback — the single redirect URI registered with the IdP. The org is derived from the signed state. MUST be registered before /:orgSlug.
Authentication: none.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
code | — | No | |
state | — | No |
curl -X GET "https://shellius.example.com/api/auth/sso/callback"200 OK
{ "success": true, "data": { … } }Per-provider callback
GET/api/auth/sso/callback/:providerId
Revision 2 — per-provider callback (this is the callbackUrl in SsoProviderDTO, registered at the IdP). Provider resolution still trusts the server-side state (not this path param) for security; the param exists so each provider gets a distinct, registerable redirect URI.
Authentication: none.
Path parameters
| Name | Type | Notes |
|---|---|---|
providerId | string |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
code | — | No | |
state | — | No |
curl -X GET "https://shellius.example.com/api/auth/sso/callback/{providerId}"200 OK
{ "success": true, "data": { … } }Sso link info
POST/api/auth/sso/link/info
What is being linked (for /sso/link)
Authentication: none.
Rate limit: 10 requests per minute per IP address.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
token | string | Yes |
curl -X POST "https://shellius.example.com/api/auth/sso/link/info" \
-H "Content-Type: application/json" \
-d '{
"token": "…"
}'200 OK
{ "success": true, "data": { … } }Sso confirm link
POST/api/auth/sso/confirm-link
Password (+ MFA) proof, then link + sign in.
Authentication: none.
Rate limit: 10 requests per minute per IP address.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
token | string | Yes | |
password | string | No | 1–200 characters. |
method | string | No | One of totp, email, backup. |
code | string | No | 1–64 characters. |
curl -X POST "https://shellius.example.com/api/auth/sso/confirm-link" \
-H "Content-Type: application/json" \
-d '{
"token": "…"
}'200 OK
{ "success": true, "data": { … } }Sso confirm link send code
POST/api/auth/sso/confirm-link/send-code
Email the MFA code (step 2)
Authentication: none.
Rate limit: 10 requests per minute per IP address.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
token | string | Yes |
curl -X POST "https://shellius.example.com/api/auth/sso/confirm-link/send-code" \
-H "Content-Type: application/json" \
-d '{
"token": "…"
}'200 OK
{ "success": true, "data": { … } }Sso link cancel
POST/api/auth/sso/link/cancel
"Cancel" on /sso/link burns the token.
Authentication: none — the token in the request is the credential.
Rate limit: 10 requests per minute per IP address.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
token | string | Yes |
curl -X POST "https://shellius.example.com/api/auth/sso/link/cancel" \
-H "Content-Type: application/json" \
-d '{
"token": "…"
}'200 OK
{ "success": true, "data": { … } }Sso link approve info
POST/api/auth/sso/link/approve-info
What the emailed approval is for.
Authentication: none.
Rate limit: 5 requests per 15 minutes per IP address.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
token | string | Yes |
curl -X POST "https://shellius.example.com/api/auth/sso/link/approve-info" \
-H "Content-Type: application/json" \
-d '{
"token": "…"
}'200 OK
{ "success": true, "data": { … } }Sso link approve
POST/api/auth/sso/link/approve
The emailed approval: links, no sign-in.
Authentication: none.
Rate limit: 5 requests per 15 minutes per IP address.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
token | string | Yes |
curl -X POST "https://shellius.example.com/api/auth/sso/link/approve" \
-H "Content-Type: application/json" \
-d '{
"token": "…"
}'200 OK
{ "success": true, "data": { … } }Sso connect providers
GET/api/auth/sso/connect/providers
The caller's org's active providers (for Profile → Sign-in methods). Same public-safe DTO as the login page.
Authentication: bearer token.
Permission: any signed-in user.
curl -X GET "https://shellius.example.com/api/auth/sso/connect/providers" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Sso connect start
POST/api/auth/sso/connect/start
Authentication: bearer token.
Permission: any signed-in user.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
providerId | string | Yes | 1–100 characters. |
curl -X POST "https://shellius.example.com/api/auth/sso/connect/start" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"providerId": "…"
}'200 OK
{ "success": true, "data": { … } }Start SSO for org
GET/api/auth/sso/:orgSlug
Authentication: none.
Path parameters
| Name | Type | Notes |
|---|---|---|
orgSlug | string |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
provider | — | No |
curl -X GET "https://shellius.example.com/api/auth/sso/{orgSlug}"200 OK
{ "success": true, "data": { … } }Legacy per-org callback
GET/api/auth/sso/:orgSlug/callback
Legacy per-org callback (kept for back-compat with older IdP registrations).
Authentication: none.
Path parameters
| Name | Type | Notes |
|---|---|---|
orgSlug | string |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
code | — | No | |
state | — | No |
curl -X GET "https://shellius.example.com/api/auth/sso/{orgSlug}/callback"200 OK
{ "success": true, "data": { … } }