Authentication
Interactive V1 clients authenticate with a username or email address and an
unchanged password at POST /v1/auth/login.
Token handling
Section titled “Token handling”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.
Login and refresh
Section titled “Login and refresh”POST /v1/auth/loginContent-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.
Current identity and sessions
Section titled “Current identity and sessions”GET /v1/auth/mereturns the current user, session, global platform roles, and current tenant/organization membership grants.GET /v1/auth/sessionslists at most ten active sessions without IP address or user-agent data.DELETE /v1/auth/sessions/{sessionId}revokes one owned session.POST /v1/auth/logoutrevokes the refresh session and clears its cookie; an exactly allowedOriginis required.POST /v1/auth/logout-allrevokes every session for the bearer-authenticated user.POST /v1/auth/change-passwordverifies 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.
Forced password change
Section titled “Forced password change”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.
Web console
Section titled “Web console”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.