TELS Auth Service - API Documentation

🏠 Home auth / api / docs

TELS Auth Service - API Documentation

Overview

Authentication & Authorization

All endpoints (except Token issuance and Diagnostics) require a valid JWT Bearer token in the Authorization header:

Authorization: Bearer <access_token>

Personas (Flags Enum)

Value Persona Description
0 None No persona assigned
1 DirectSupplyPartner Internal DS employee/partner
2 Customer TELS customer (facility operator)
4 ServiceProvider External service provider/technician
8 Resident Facility resident
16 Owner Facility owner

Authorization Levels

Attribute Requirement
[Authorize] Valid JWT Bearer token
[AuthorizeInternalAdministrator] DirectSupplyPartner persona OR CustomerGlobalAdministrator role
[FromAuth] Binds ITokenClaims from JWT claims (custom model binder)

Token Controller

Route Prefix: auth/token Authorization: [AllowAnonymous] — no token required (this is the token issuance endpoint)

Method Path Auth Description
POST /auth/token/refresh None Exchange refresh token for new access + refresh tokens
POST /auth/token/user None Authenticate with username/password
POST /auth/token/trust None Service-to-service auth with HMAC signature
POST /auth/token/trust-simple None Service-to-service auth with shared secret
POST /auth/token/bearer None Exchange an existing bearer token
POST /auth/token/openId None Authenticate via OpenID Connect (Entra ID)
GET /auth/token/sso/initiate None Initiate SSO flow — redirects to identity provider
GET /auth/token/user/winauth None OBSOLETE — Windows auth, use sso/initiate
POST /auth/token/user/AzureADLogOn None OBSOLETE — Azure AD, use openId
POST /auth/token/trustedToken None OBSOLETE — use bearer

POST /auth/token/refresh

Exchange a valid refresh token for a new access token and refresh token pair.

Request Body:

{
  "refreshToken": "string (required)",
  "hmacSigning": true
}
Field Type Required Description
refreshToken string Yes Previously issued refresh token
hmacSigning bool? No Use HMAC signing for new token (default: true)

Response (200 OK):

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
  "rejectionReason": 0,
  "rejectionDetails": null,
  "wasSuccessful": true
}

Error Responses: 400, 401, 422


POST /auth/token/user

Authenticate using username and password credentials.

Request Body:

{
  "user": "string",
  "password": "string"
}

Query Parameters: - grantAsDsPartner (bool?, optional) — Grant DirectSupplyPartner persona if eligible

Response: TokenResponse (200 OK)

Error Responses: 400, 401, 422

Note: This endpoint has sensitive logging enabled (credentials are not logged).


POST /auth/token/trust

Service-to-service authentication using HMAC-signed requests. Used by other TELS microservices (Tasks, BusProxy, etc.).

Request Body:

{
  "requestTimestampUtc": "2026-03-11T12:00:00Z",
  "applicationKey": "string (required)",
  "authenticationCode": "string (required, HMAC signature)",
  "persona": 1,
  "userName": "string (required)",
  "serviceProviderID": null,
  "name": null,
  "userAccountID": null,
  "personID": null
}
Field Type Required Description
requestTimestampUtc string (ISO 8601) Yes Request timestamp for replay protection
applicationKey string Yes Identifies the calling application
authenticationCode string Yes HMAC signature computed with shared secret
persona Personas (int) Yes Requested persona for the token
userName string Yes Username to issue token for
serviceProviderID int? No Service provider ID (for SP persona)
name string? No Technician name (for SP persona)
userAccountID int? No Explicit UserAccount ID
personID int? No Explicit Person ID

Response: TokenResponse (200 OK)

Error Responses: 400, 401, 422


POST /auth/token/trust-simple

Simplified service-to-service authentication using a plain shared secret (no HMAC computation required).

Request Body:

{
  "applicationKey": "string (required)",
  "sharedSecret": "string (required)",
  "persona": 1,
  "userName": "string (required)",
  "serviceProviderID": null,
  "name": null,
  "userAccountID": null,
  "personID": null
}

Response: TokenResponse (200 OK)

Error Responses: 400, 401, 422

Note: Sensitive logging enabled (shared secret is not logged).


POST /auth/token/bearer

Exchange an existing valid bearer token for a new token. Used for token refresh/exchange scenarios.

Headers:

Authorization: Bearer <existing_token>

Query Parameters: - bearerTokenOverride (string?, optional) — Override bearer token (test environments only)

Response: TokenResponse (200 OK)

Error Responses: 401


POST /auth/token/openId

Authenticate using an OpenID Connect token from Microsoft Entra ID.

Request Body: Form data (OpenID Connect callback parameters)

Response: TokenResponse (200 OK)

Error Responses: 400, 401


GET /auth/token/sso/initiate

Initiate an SSO authentication flow. Redirects the user to the configured external identity provider (Microsoft Entra ID).

Response: 302 Redirect to identity provider authorization endpoint


Authorization Controller

Route Prefix: auth Authorization: [Authorize] + [AuthorizeInternalAdministrator]

Method Path Auth Description
GET /auth/roles/{identifier}/members Internal Admin Get members of a security role
GET /auth/accessPoints/{identifier}/hasAccess Internal Admin Check if user has access to an access point

GET /auth/roles/{identifier}/members

Retrieve all members of a security group using recursive hierarchy traversal.

Route Parameters: - identifier — CompositeIdentifier format: SecurityEditor~~GroupName~~ACTUAL_GROUP_NAME

Response (200 OK):

{
  "members": [
    {
      "type": "string",
      "key": "string",
      "value": "string"
    }
  ],
  "identityNames": ["John Smith", "Jane Doe"]
}

Error Responses: 400, 401, 403


GET /auth/accessPoints/{identifier}/hasAccess

Check if a user has access to a specific access point.

Route Parameters: - identifier — CompositeIdentifier format

Query Parameters: - expectedUserId (int?, optional) — User ID to check access for (defaults to token claims)

Response (200 OK):

{
  "hasAccess": true
}

Error Responses: 400, 401, 403


Revocations Controller

Route Prefix: auth/revocations Authorization: [Authorize]

Method Path Auth Description
GET /auth/revocations Internal Admin List all revocations after a date
GET /auth/revocations/{domain}/{identifier} Bearer Get specific revocation
PUT /auth/revocations/{domain}/{identifier} Bearer Create/update a revocation

GET /auth/revocations

Retrieve all revocations after a specified date. Requires Internal Administrator authorization.

Query Parameters: - minDate (string?, optional) — DateTimeOffset format, defaults to 2018-11-19

Response (200 OK):

[
  {
    "domain": "tels-personid",
    "identifier": "12345",
    "revocationDate": "2026-03-11T10:30:00Z"
  }
]

Error Responses: 400, 401, 403


GET /auth/revocations/{domain}/{identifier}

Get a specific revocation record.

Route Parameters: - domain — Revocation domain: tels-personid, ds-mtolympus, jti, or token (alias for jti) - identifier — The revoked entity identifier

Response (200 OK):

{
  "domain": "tels-personid",
  "identifier": "12345",
  "revocationDate": "2026-03-11T10:30:00Z"
}

Error Responses: 400, 401, 403, 404


PUT /auth/revocations/{domain}/{identifier}

Create or update a revocation. Uses MERGE (upsert) — sets RevocationDate to current UTC time.

Route Parameters: Same as GET

Response: 200 OK (empty body)

Error Responses: 400, 401, 403


Diagnostic Controller

Route Prefix: auth/diagnostics Authorization: None (anonymous)

Method Path Auth Description
GET /auth/diagnostics/ping None Health check — returns "Pong"
GET /auth/diagnostics/version None Returns assembly version

GET /auth/diagnostics/ping

Health check endpoint.

Response (200 OK): "Pong" (string)


GET /auth/diagnostics/version

Returns the running assembly version.

Response (200 OK): "1.2.3" (string)


BusinessUnit Controller (DEPRECATED)

Route Prefix: auth/buid Authorization: [Authorize] Note: This controller is deprecated — consumers should call the Customers Service directly.

Method Path Auth Description
GET /auth/buid/{businessUnitId}/facility-access Bearer Get facility IDs for a business unit
GET /auth/buid Bearer Get business unit ID by PLT code

GET /auth/buid/{businessUnitId}/facility-access

Proxy to Customers Service — returns facility IDs accessible by a business unit.

Route Parameters: - businessUnitId (int) — Business unit ID

Response (200 OK):

[1234, 5678, 9012]

Error Responses: 400, 401, 403, 404


GET /auth/buid

Proxy to Customers Service — resolves a PLT code to a business unit ID.

Query Parameters: - plt (string, required) — PLT code to resolve

Response (200 OK): 12345 (int)

Error Responses: 400, 401, 403, 404


Key Data Contracts

TokenResponse

{
  "accessToken": "string (JWT) | null",
  "refreshToken": "string (JWT) | null",
  "rejectionReason": 0,
  "rejectionDetails": "string | null",
  "wasSuccessful": true
}
Field Type Description
accessToken string? Issued JWT access token (24h lifetime)
refreshToken string? Issued JWT refresh token (365d lifetime, only for authorized apps)
rejectionReason TokenRejectionReason Enum indicating success or failure reason
rejectionDetails string? Human-readable error details
wasSuccessful bool Computed: rejectionReason == Successful

TokenRejectionReason (Enum)

Value Name Description
0 Successful Authentication succeeded
1 AuthenticationFailed Invalid credentials
2 AccessTokenIsNotValid Bearer token validation failed
3 RefreshThresholdExceeded Refresh token is too old
4 RefreshTokenIsNotValid Refresh token validation failed
5 UnsupportedRefreshIdentity Identity type cannot be refreshed
6 TokenRevoked Token has been revoked
7 InvalidRequest Request format/content invalid
8 InvalidGrant Grant type not permitted

Revocation

{
  "domain": "tels-personid | ds-mtolympus | jti",
  "identifier": "string",
  "revocationDate": "2026-03-11T10:30:00+00:00"
}

Global Response Codes

Code Meaning
200 Success
302 Redirect (SSO flows)
400 Bad Request — validation error
401 Unauthorized — invalid or missing credentials/token
403 Forbidden — insufficient persona/role
404 Not Found — resource does not exist
422 Unprocessable Entity — valid request but business rule rejection

Error Handling

Token endpoint errors return a TokenResponse with wasSuccessful: false and a specific rejectionReason. Other endpoints return standard HTTP error codes.

Database Retry Policy


Notes