auth/Asp.Versioning)All endpoints (except Token issuance and Diagnostics) require a valid JWT Bearer token in the Authorization header:
Authorization: Bearer <access_token>
| 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 |
| Attribute | Requirement |
|---|---|
[Authorize] |
Valid JWT Bearer token |
[AuthorizeInternalAdministrator] |
DirectSupplyPartner persona OR CustomerGlobalAdministrator role |
[FromAuth] |
Binds ITokenClaims from JWT claims (custom model binder) |
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 |
/auth/token/refreshExchange 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
/auth/token/userAuthenticate 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).
/auth/token/trustService-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
/auth/token/trust-simpleSimplified 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).
/auth/token/bearerExchange 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
/auth/token/openIdAuthenticate 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
/auth/token/sso/initiateInitiate an SSO authentication flow. Redirects the user to the configured external identity provider (Microsoft Entra ID).
Response: 302 Redirect to identity provider authorization endpoint
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 |
/auth/roles/{identifier}/membersRetrieve 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
/auth/accessPoints/{identifier}/hasAccessCheck 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
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 |
/auth/revocationsRetrieve 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
/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
/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
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 |
/auth/diagnostics/pingHealth check endpoint.
Response (200 OK): "Pong" (string)
/auth/diagnostics/versionReturns the running assembly version.
Response (200 OK): "1.2.3" (string)
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 |
/auth/buid/{businessUnitId}/facility-accessProxy 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
/auth/buidProxy 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
{
"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 |
| 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 |
{
"domain": "tels-personid | ds-mtolympus | jti",
"identifier": "string",
"revocationDate": "2026-03-11T10:30:00+00:00"
}
| 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 |
Token endpoint errors return a TokenResponse with wasSuccessful: false and a specific rejectionReason. Other endpoints return standard HTTP error codes.
SqlServerTransientExceptionDetectorapplicationKey and sharedSecret. The HMAC variant requires the caller to compute authenticationCode = HMAC-SHA256(requestTimestampUtc + applicationKey, sharedSecret).GET /auth/token/sso/initiate redirects to Microsoft Entra ID, which calls back to POST /auth/token/openId with the authorization code.winauth, AzureADLogOn, and trustedToken are marked obsolete and will be removed in a future version.v2/businessUnits/{id}/facilityAccess.