Authentication

Log out (server-side token revocation)

  • Sandbox: available
  • Staging: available
  • Production: unknown
POST
/v1/auth/logout

Signs the caller out on the server: the access token in the Authorization header stops working for every authenticated route, although it has not expired.

Auth: bearer token. A missing or invalid token gives 401.

Behaviour

  • Ovok adds the token to a denylist. The entry lasts for the rest of the token's lifetime (its exp claim), so the list never outgrows the set of live tokens.
  • Only this access token is revoked. The refresh token is not touched here; to end other sessions use DELETE /auth/session/{option}.
  • The call is idempotent: repeating it with the same token returns 204 with no further effect. A token without an exp claim, or one that has already expired, is ignored.
  • If the denylist store is unavailable the call still returns 204, and the token stays valid until it expires. Clear the local session as well.
  • The response has no body (204 No Content).
  • The route is available at both /auth/logout and /v1/auth/logout.

Example

curl -X POST 'https://api.sandbox.ovok.com/v1/auth/logout' \  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk'

Response Body

Token was added to the revocation denylist. Returns 204 No Content.

Example Request
curl -X POST 'https://api.sandbox.ovok.com/v1/auth/logout'
Example Response
Empty

Refresh access token POST

Exchanges a refresh token for a new access token and a new refresh token. Call it before the access token expires to keep a session alive. **Auth:** none. The refresh token in the body is the credential. ## Behaviour - Ovok forwards the token to Medplum's `oauth2/token` endpoint (`grant_type=refresh_token`, scope `openid offline_access`). - The request body takes the token as `refresh_token`. - The response holds `accessToken`, `refreshToken` and `expiresIn` (seconds), the same names the login routes use. Store the new `refreshToken`: use it for the next refresh. - The response also carries the same three values as `access_token`, `refresh_token` and `expires_in`. Those names are deprecated and will be removed in a later release: read the camelCase ones. - A refresh token Medplum refuses (spent, expired, revoked, or not a refresh token at all) gives a 401 with Medplum's error description. A refresh token is single-use, so retrying it after a successful refresh also gives a 401: sign in again. - A body without `refresh_token` gives a 400. - A session of a Patient whose project turned `PATIENT_LOGIN_ENABLED` off, or of a Practitioner whose project turned `PRACTITIONER_LOGIN_ENABLED` off, gives a 403 `Login is not enabled for this project.` That ends the session: the refresh token is used up, and signing in again is refused while login is off. A Practitioner who is a project admin is not refused, so an admin who is signed in can still turn login back on (they cannot sign in again while it is off). The access token already issued lasts until it expires (60 minutes). - `POST /oauth2/token` applies the same check to every token it grants (refresh and code exchange), answering `403 { "error": "access_denied", "error_description": "Login is not enabled for this project." }`. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/auth/refresh-token' \ -H 'Content-Type: application/json' \ -d '{ "refresh_token": "example.jwt.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk" }' ```

Log out (server-side token revocation) POST

Signs the caller out on the server: the access token in the `Authorization` header stops working for every authenticated route, although it has not expired. **Auth:** bearer token. A missing or invalid token gives 401. ## Behaviour - Ovok adds the token to a denylist. The entry lasts for the rest of the token's lifetime (its `exp` claim), so the list never outgrows the set of live tokens. - Only this access token is revoked. The refresh token is not touched here; to end other sessions use `DELETE /auth/session/{option}`. - The call is idempotent: repeating it with the same token returns 204 with no further effect. A token without an `exp` claim, or one that has already expired, is ignored. - If the denylist store is unavailable the call still returns 204, and the token stays valid until it expires. Clear the local session as well. - The response has no body (204 No Content). - The route is available at both `/auth/logout` and `/v1/auth/logout`. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/v1/auth/logout' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' ```