Skip to content
SENS Platform Docs

Authentication

Interactive V1 clients authenticate with a username or email address and an unchanged password at POST /v1/auth/login.

The response contains a bearer access token valid for 1,800 seconds. A browser must keep this token in memory only and send it as:

Authorization: Bearer <access-token>

Never place access or refresh tokens in localStorage, sessionStorage, URLs, logs, analytics events, or error reports.

When product analytics is enabled, GET /v1/auth/me adds an optional analytics object with schemaVersion: 1, one 43-character pseudonymous subjectId, and pseudonymous IDs keyed by the actor’s tenant IDs. The field is absent when analytics is disabled. It is not an authorization input and exposes no names, e-mail addresses, or unhashed internal IDs.

The refresh token is an opaque rotating credential. It is never returned in the JSON body. Test and production receive it in the Secure, host-only, HttpOnly, SameSite=Strict cookie __Host-sens_refresh. Local plain HTTP uses sens_refresh without Secure.

POST /v1/auth/login
Content-Type: application/json
{"identifier":"operator@example.com","password":"exact user input"}

A successful login or refresh returns:

{
"accessToken": "...",
"tokenType": "Bearer",
"expiresInSeconds": 1800,
"refreshIdleExpiresAt": "2026-08-10T12:00:00.000Z",
"passwordChangeRequired": false
}

Call POST /v1/auth/refresh with browser credentials enabled and an Origin header that exactly matches the configured allowlist. Each successful refresh rotates the cookie and moves the seven-day inactivity deadline. A 409 with Retry-After: 1 means another request used the same token within the protected race window; retry once with the current cookie. Reuse after that window revokes the session.

  • GET /v1/auth/me returns the current user, session, global platform roles, and current tenant/organization membership grants.
  • GET /v1/auth/sessions lists at most ten active sessions without IP address or user-agent data.
  • DELETE /v1/auth/sessions/{sessionId} revokes one owned session.
  • POST /v1/auth/logout revokes the refresh session and clears its cookie; an exactly allowed Origin is required.
  • POST /v1/auth/logout-all revokes every session for the bearer-authenticated user.
  • POST /v1/auth/change-password verifies the current password, replaces it, revokes every session, and returns one new current session.

All authentication responses use Cache-Control: no-store. Bearer failures include WWW-Authenticate: Bearer.

An administrator CLI password reset sets passwordChangeRequired=true. Until the password is changed, the session can use only me, change-password, and logout endpoints. Other protected actions return 403.

Invalid identifiers, incorrect passwords, disabled users, and accounts without local credentials use the same generic login failure. Login throttling returns 429 with Retry-After; clients must not repeatedly retry before that delay.

Future OIDC login, MFA, service accounts, personal access tokens, and email password reset are outside this V1 slice.

Test operators can validate these endpoints at https://test-frontend.dev.iot-sens.schlossers.at. The permanent web-console uses the current platform APIs, shows roles and grants from /me, and keeps access tokens in memory. The prepared Production configuration uses the same contract at https://app.iot-sens.schlossers.at; each environment accepts only its exact configured browser origins.