Files
sso-manager-node/API.md
T
2026-07-01 11:10:09 -04:00

21 KiB

SSO Manager API Documentation

Overview

API documentation for the SSO Manager Node application. Provides endpoints for authentication, user management, group management, token management, notifications, and OAuth 2.0 / OpenID Connect.

Base URL: https://your-domain.com

Content Type: application/json (all request and response bodies)


Authentication

Getting a Token

Login via POST /api/auth/login to receive an auth token.

Using the Token

Include the token in every protected request:

auth-token: <token>

Protected Routes

  • /api/user/* — user management
  • /api/group/* — group management
  • /api/token/* — token management
  • /api/notification/* — notifications
  • /api/oauth/client/* — OAuth client management

Permission Groups

Group Grants
app_sso_admin Full user/group/notification management
app_sso_oauth_admin Register and manage OAuth clients
Group owner Manage membership of that specific group

Self-service: users can always read and modify their own account without admin membership.

Rate Limits

Endpoint Limit
POST /api/auth/login 10 requests / 15 min
POST /api/auth/resetpassword 5 requests / hour
POST /api/auth/otp/request 5 requests / 15 min
POST /api/auth/otp/verify 10 requests / 15 min
POST /api/auth/invite/* 20 requests / hour

Limits are per IP. The server must be behind a trusted proxy for these to apply correctly.


Authentication Endpoints

Base path: /api/auth

Login

POST /api/auth/login — No auth required

Request:

{ "uid": "username", "password": "user_password" }

Response:

{ "login": true, "token": "auth_token_string", "message": "username logged in!" }

Logout

ALL /api/auth/logout — No auth required

Response:

{ "message": "Bye" }

Username Suggestions

Returns available username suggestions based on name and optional date of birth.

GET /api/auth/username-suggestions — No auth required

Query Parameters:

  • givenName — First name
  • sn — Last name
  • dob (optional) — Date of birth (used to generate year-variant suggestions)

Response:

{ "suggestions": ["jsmith", "jsmith1990", "johnsmith"] }

Request Password Reset

POST /api/auth/resetpassword — No auth required

Request:

{ "mail": "user@example.com" }

Response:

{ "message": "If the emaill address is in our system, you will receive a message." }

The same response is returned whether or not the email exists. Reset tokens expire after 24 hours.


Complete Password Reset

POST /api/auth/resetpassword/:token — No auth required

URL Parameters: token — from the reset email

Request:

{ "password": "new_password", "confirm": "new_password" }

Response:

{ "message": "Password has been changed." }

The token is invalidated after a successful reset.


Request OTP Code

Send a one-time login code via email or SMS.

POST /api/auth/otp/request — No auth required

Request:

{ "login": "username_or_email", "method": "email" }

method must be email or sms. For sms, the account must have a mobile number on file.

Response:

{ "message": "Code sent", "method": "email", "expires_at": 1234567890000 }

Verify OTP Code

Verify a one-time code and receive an auth token. Also marks the corresponding contact method (email or phone) as verified on the account.

POST /api/auth/otp/verify — No auth required

Request:

{ "login": "username_or_email", "code": "123456" }

Response:

{ "login": true, "token": "auth_token_string" }

Returns 401 if the code is invalid or expired.


Accept Invite (with Email Verification)

Create an account from an invite token after verifying email.

POST /api/auth/invite/:token/:mailToken — No auth required

URL Parameters: token — invite token, mailToken — email verification token

Request:

{
  "uid": "username",
  "password": "user_password",
  "givenName": "First Name",
  "sn": "Last Name",
  "mail": "user@example.com"
}

Response:

{ "user": "username", "token": "auth_token_string" }

Send Invite Verification Email

Send an email verification link for an invite token.

POST /api/auth/invite/:token — No auth required

URL Parameters: token — invite token

Request:

{ "mail": "user@example.com" }

Response:

{ "message": "sent" }

Impersonate User (Admin)

Creates a temporary password for a target user and returns it. Allows admins to log in as another user for support purposes.

POST /api/auth/impersonate/:uid — Auth required, app_sso_admin

URL Parameters: uid — target username

Response:

{
  "uid": "target_username",
  "temp_password": "random_temp_password",
  "expires_at": 1234567890000
}

The temp password is short-lived. Any previous impersonation session for the same target is revoked first.


End Impersonation (Admin)

Revoke all active impersonation sessions for a user.

DELETE /api/auth/impersonate/:uid — Auth required, app_sso_admin

URL Parameters: uid — target username

Response:

{ "message": "Impersonation ended for username", "revoked": 1 }

User Management Endpoints

Base path: /api/user

All endpoints require authentication.

List All Users

GET /api/user/app_sso_admin required

Query Parameters:

  • detail (optional) — return full user objects instead of a minimal list

Response:

{
  "results": [
    { "uid": "username", "mail": "user@example.com", "givenName": "First", "sn": "Last" }
  ]
}

Create User

POST /api/user/app_sso_admin required

Request:

{
  "uid": "username",
  "password": "user_password",
  "givenName": "First Name",
  "sn": "Last Name",
  "mail": "user@example.com"
}

Response:

{ "results": { "uid": "username", "dn": "uid=username,ou=people,dc=..." } }

Admin-created accounts have password_must_change set automatically.


Get Current User

GET /api/user/me — Any authenticated user

Returns the full user object for the authenticated user, including onboarding state.

Response:

{
  "uid": "username",
  "mail": "user@example.com",
  "givenName": "First",
  "sn": "Last",
  "dn": "uid=username,ou=people,dc=...",
  "onboardingRequired": "yes",
  "onboardingNeeds": ["tos", "dob", "password"],
  "memberOf": ["cn=group_name,ou=groups,dc=..."]
}

onboardingRequired is "yes" when onboardingNeeds is non-empty. Needs can be "tos", "dob", or "password".


Accept Terms of Service

Mark TOS as accepted for the authenticated user.

POST /api/user/accept-tos — Any authenticated user

Response:

{ "success": true }

Get Admin Stats

Returns user and group counts, recent signups, and inactive users.

GET /api/user/statsapp_sso_admin required

Response:

{
  "totalUsers": 42,
  "activeUsers": 38,
  "inactiveUsers": 4,
  "totalGroups": 10,
  "recentSignups": [
    { "uid": "newuser", "givenName": "New", "sn": "User", "mail": "new@example.com", "createTimestamp": "20240101000000Z" }
  ],
  "inactiveList": [
    { "uid": "lockeduser", "givenName": "Locked", "sn": "User", "mail": "locked@example.com" }
  ]
}

Export Users CSV

Download all users as a CSV file.

GET /api/user/exportapp_sso_admin required

Response: Content-Type: text/csv, attachment download

Columns: uid, givenName, sn, mail, mobile, uidNumber, isActive, createTimestamp


Get User Verification Status

GET /api/user/:uid/verificationapp_sso_admin required

Response:

{
  "uid": "username",
  "emailVerified": true,
  "emailVerifiedAt": 1234567890000,
  "phoneVerified": false,
  "phoneVerifiedAt": null,
  "tosAccepted": true,
  "tosAcceptedAt": 1234567890000
}

Get User

GET /api/user/:uid — Any authenticated user

Response:

{ "results": { "uid": "username", "mail": "user@example.com", "givenName": "First", "sn": "Last" } }

Update User

PUT /api/user/:uid — Own account, or app_sso_admin for others

Request: Any subset of editable fields:

{
  "givenName": "New First Name",
  "sn": "New Last Name",
  "mail": "newemail@example.com",
  "dateOfBirth": "1990-01-15",
  "mobile": "+15551234567",
  "sshPublicKey": "ssh-rsa AAAA..."
}

Response:

{ "results": { <updated user object> }, "message": "Updated username user" }

Set User Active/Inactive

Lock or unlock a user account.

PUT /api/user/:uid/activeapp_sso_admin required

Request:

{ "active": true }

Response:

{ "uid": "username", "active": true, "message": "User username activated" }

Delete User

DELETE /api/user/:uid — Own account, or app_sso_admin for others

Response:

{ "uid": "username", "results": true }

Change Own Password

PUT /api/user/password — Any authenticated user

Request:

{ "password": "new_password", "confirm": "new_password" }

Response:

{ "results": true }

Clears password_must_change on the account.


Change User Password (Admin)

PUT /api/user/:uid/password — Own account, or app_sso_admin for others

Request:

{ "password": "new_password", "confirm": "new_password" }

Response:

{ "results": true, "message": "User username password changed." }

When an admin changes another user's password, password_must_change is set on that account.


Generate Invite Token

POST /api/user/invite — Any authenticated user

Response:

{ "token": "invite_token_string" }

Add SSH Key

POST /api/user/key — Any authenticated user

Request:

{ "key": "ssh-rsa AAAAB3NzaC1yc2E... user@host" }

Response:

  • 200{ "message": true }
  • 400{ "message": "error description" }

Group Management Endpoints

Base path: /api/group

All endpoints require authentication.

List Groups

GET /api/group/ — Any authenticated user

Query Parameters:

  • detail (optional) — return full group objects
  • member (optional) — filter to groups containing this UID as a member

Response:

{ "results": [{ "cn": "group_name", "description": "Group description" }] }

Create Group

POST /api/group/app_sso_admin required

Request:

{ "name": "group_name", "description": "Group description" }

Response:

{ "results": { "cn": "group_name" }, "message": "group_name was added!" }

The authenticated user is automatically set as the group owner.


Get Group

GET /api/group/:name — Any authenticated user

Response:

{
  "results": {
    "cn": "group_name",
    "description": "Group description",
    "member": ["uid=user1,ou=people,dc=...", "uid=user2,ou=people,dc=..."],
    "owner": ["uid=owner,ou=people,dc=..."]
  }
}

Add Group Owner

PUT /api/group/owner/:group/:uidapp_sso_admin or group owner

Response:

{ "results": true, "message": "Added owner uid to group group." }

Remove Group Owner

DELETE /api/group/owner/:group/:uidapp_sso_admin or group owner

Response:

{ "results": true, "message": "Removed Owner uid from group group." }

Add User to Group

PUT /api/group/:group/:uidapp_sso_admin or group owner

Response:

{ "results": true, "message": "Added user uid to group group." }

Remove User from Group

DELETE /api/group/:group/:uidapp_sso_admin or group owner

Response:

{ "results": true, "message": "Removed user uid from group group." }

Delete Group

DELETE /api/group/:groupapp_sso_admin or group owner

Response:

{ "removed": true, "results": { "cn": "group_name" }, "message": "Group group_name Deleted" }

Token Management Endpoints

Base path: /api/token

All endpoints require authentication.

List Token Types

GET /api/token/ — Any authenticated user

Response:

{ "results": ["InviteToken", "PasswordResetToken"] }

List Tokens by Type

GET /api/token/:name — Any authenticated user

Query Parameters: detail (optional) — include full token objects

Response:

{
  "results": [
    { "token": "token_string", "created_by": "username", "created_on": 1234567890000, "is_valid": true }
  ]
}

Get Specific Token

GET /api/token/:name/:token — Any authenticated user

Response:

{ "results": { "token": "token_string", "created_by": "username", "created_on": 1234567890000, "is_valid": true } }

Notification Endpoints

Base path: /api/notification

All endpoints require authentication and app_sso_admin membership.

Notifications send email blasts to filtered groups of users and record history.

Send Notification

POST /api/notificationapp_sso_admin required

Request:

{
  "subject": "Maintenance window tonight",
  "message": "<p>We will be performing maintenance starting at midnight.</p>",
  "filter_type": "group",
  "filter_value": "host_hec-bot_admin, app_sso_admin",
  "active_only": true
}

filter_type values:

Value Description
all_active All active (unlocked) users
all All users including inactive
group Members of one or more LDAP groups
users Specific users by UID

filter_value:

  • For group: comma-separated group names (e.g. "host_hec-bot_admin, app_sso_admin")
  • For users: JSON array of UIDs (e.g. '["wmantly","jsmith"]')
  • Unused for all_active and all

active_only (boolean, default false): when true with group or all filter types, only active (unlocked) users receive the notification. Has no effect on all_active (which is always active-only).

Response:

{
  "results": {
    "notification_id": "uuid",
    "created_by": "wmantly",
    "created_on": 1234567890000,
    "subject": "Maintenance window tonight",
    "message": "<p>...</p>",
    "filter_type": "group",
    "filter_value": "host_hec-bot_admin",
    "active_only": true,
    "status": "sent",
    "sent_count": 5,
    "failed_count": 0,
    "sent_at": 1234567890123
  }
}

External API usage example:

# Login once, store token
TOKEN=$(curl -s -X POST https://sso.example.com/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"uid":"monitor","password":"..."}' | jq -r .token)

# Send notification to a group
curl -X POST https://sso.example.com/api/notification \
  -H "auth-token: $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "subject": "hec-bot maintenance",
    "message": "<p>The hec-bot VM will restart at 3am.</p>",
    "filter_type": "group",
    "filter_value": "host_hec-bot_admin",
    "active_only": true
  }'

List Notification History

GET /api/notificationapp_sso_admin required

Response:

{
  "results": [
    {
      "notification_id": "uuid",
      "subject": "Maintenance window",
      "filter_type": "group",
      "filter_value": "host_hec-bot_admin",
      "active_only": true,
      "status": "sent",
      "sent_count": 5,
      "failed_count": 0,
      "created_by": "wmantly",
      "created_on": 1234567890000,
      "sent_at": 1234567890123
    }
  ]
}

Results are sorted by created_on descending (most recent first).


Get Notification Record

GET /api/notification/:idapp_sso_admin required

Response: { "results": { <notification object> } }


OAuth 2.0 / OpenID Connect

The SSO Manager acts as an OAuth 2.0 Authorization Server and OpenID Connect Provider.

Discovery

GET /.well-known/openid-configuration — No auth required

Returns the OIDC discovery document with endpoint URLs, supported scopes, and signing algorithms.


Authorization Endpoint

GET /oauth/authorize — No auth required (redirects to login if not authenticated)

Query Parameters:

  • response_type — Must be code
  • client_id — Registered OAuth client ID
  • redirect_uri — Must exactly match a URI registered for the client
  • scope — Space-separated: openid, profile, email
  • state — Opaque value returned unchanged in the redirect
  • code_challenge — PKCE challenge (SHA-256 of code_verifier, base64url-encoded)
  • code_challenge_method — Must be S256

Renders the consent screen. On approval, redirects to redirect_uri?code=<code>&state=<state>.


Token Endpoint

POST /oauth/token — No auth required (client authenticates via credentials)

Content-Type: application/x-www-form-urlencoded or application/json

Client Authentication: client_id + client_secret in the request body, or HTTP Basic Auth.

Authorization Code Grant

grant_type=authorization_code
&code=<auth_code>
&redirect_uri=<redirect_uri>
&client_id=<client_id>
&client_secret=<client_secret>
&code_verifier=<pkce_verifier>

Refresh Token Grant

grant_type=refresh_token
&refresh_token=<refresh_token>
&client_id=<client_id>
&client_secret=<client_secret>

Refresh tokens are rotated on each use — the old token is invalidated and a new one is returned.

Response:

{
  "access_token": "uuid",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "uuid",
  "id_token": "<jwt>"
}

UserInfo Endpoint

GET /oauth/userinfo — Bearer token required (Authorization: Bearer <access_token>)

Response (claims vary by granted scopes):

{
  "sub": "username",
  "name": "First Last",
  "given_name": "First",
  "family_name": "Last",
  "preferred_username": "username",
  "email": "user@example.com"
}

OAuth Client Management

Base path: /api/oauth/client

All endpoints require authentication and app_sso_oauth_admin membership.

List Clients

GET /api/oauth/client/

Response:

{
  "results": [
    {
      "client_id": "uuid",
      "name": "Home Assistant",
      "description": "Home automation",
      "redirect_uris": ["https://ha.example.com/auth/external/callback"],
      "scopes": ["openid", "profile", "email"],
      "token_lifetime": { "access_token": 3600, "refresh_token": 2592000 },
      "created_by": "wmantly",
      "created_on": 1234567890000
    }
  ]
}

Register Client

POST /api/oauth/client/

Request:

{
  "name": "Home Assistant",
  "description": "Home automation dashboard",
  "redirect_uris": ["https://ha.example.com/auth/external/callback"],
  "scopes": ["openid", "profile", "email"],
  "token_lifetime": { "access_token": 3600, "refresh_token": 2592000 }
}

redirect_uris may also be a newline-separated string. scopes may also be a space-separated string.

Response:

{
  "results": { "client_id": "uuid", "name": "Home Assistant" },
  "client_secret": "raw-secret-shown-once",
  "message": "OAuth client 'Home Assistant' created. Save the client secret — it will not be shown again."
}

The client_secret is shown only once. Store it immediately.


Get Client

GET /api/oauth/client/:client_id

Response: { "results": { <client object> } }


Update Client

PUT /api/oauth/client/:client_id

Request: Any subset of name, description, redirect_uris, scopes, token_lifetime, is_valid.

Response: { "results": { <updated client> }, "message": "..." }


Delete Client

DELETE /api/oauth/client/:client_id

Response: { "client_id": "uuid", "message": "OAuth client '...' deleted." }


Rotate Client Secret

POST /api/oauth/client/:client_id/rotate

Response:

{
  "client_secret": "new-raw-secret-shown-once",
  "message": "Client secret rotated for '...'. Save it — it will not be shown again."
}

The old secret is invalidated immediately. The new secret is shown only once.


Token Lifetimes

Configurable per-client via token_lifetime. Global defaults (in seconds):

{ "access_token": 3600, "refresh_token": 2592000 }

Error Responses

All endpoints return errors in this format:

{ "name": "ErrorName", "message": "Error message description" }

HTTP Status Codes

Code Meaning
200 Success
400 Bad Request — invalid input
401 Unauthorized — auth required, token invalid, or insufficient permission
404 Not Found
429 Too Many Requests — rate limit exceeded
500 Internal Server Error
502 Bad Gateway — upstream service failure (e.g. SMS delivery)