Tenant Authentication

Start related person login

  • Sandbox: available
  • Staging: available
  • Production: unknown
POST
/auth/tenant/RelatedPerson/login/start

Starts a related person (carer) login for one tenant: checks the email and password and returns either a session code to exchange for tokens or, when the user has MFA enrolled, a login ID for the MFA step.

Auth: none. The tenant is named by tenantCode. Scope: the project that owns tenantCode.

Behaviour

  • This is step 1 of a PKCE login. Generate a random codeVerifier, send its S256 hash as codeChallenge here, and send the codeVerifier itself to POST /auth/tenant/RelatedPerson/login/token.
  • The account must be a RelatedPerson of the tenant's project. A carer account is made only by accepting a record-share invite (POST /v1/invites/record-share/accept); there is no register route. A Patient or Practitioner with the same email cannot log in here.
  • RELATED_PERSON_LOGIN_ENABLED on the project must not be false (it defaults to on). It is the carers' own switch: PATIENT_LOGIN_ENABLED does not apply to them.
  • Response nextStep:
    • token: no MFA. Pass sessionCode to login/token.
    • mfa: the user has MFA enrolled. Pass loginId and the current TOTP code to POST /auth/tenant/RelatedPerson/login/mfa.
  • A wrong email, an unknown account, an account without a password and a wrong password all give the same 401 Invalid email or password.
  • After 5 failed sign-ins for one email within 15 minutes, that email's sign-ins answer 429 with Retry-After for 15 minutes, the right password included, whether or not the email has an account. A successful sign-in resets the count.
  • A forgotten password is reset through POST /v2/auth/reset-password with "type": "RelatedPerson" and the app's clientId.
  • Error responses are delayed to take at least one second.

Example

curl -X POST 'https://api.sandbox.ovok.com/auth/tenant/RelatedPerson/login/start' \  -H 'Content-Type: application/json' \  -d '{    "email": "max.mustermann@example.com",    "password": "your-password",    "tenantCode": "my-medical-project",    "codeChallenge": "<base64url S256 hash of your codeVerifier>"  }'

Request Body

application/json
  1. body
email*string
Formatemail
password*string
tenantCode*string

Tenant code, e.g. "big-health-company"

codeChallenge*string

A randomly generated text that is sent from client application, the client application should generate it using the codeVerifier from the challange

Response Body

The next step: a session code for login/token, or a login ID for login/mfa.

application/json
  1. response
nextStep*"token"
Value in"token"
sessionCode*string
Example Request
curl -X POST 'https://api.sandbox.ovok.com/auth/tenant/RelatedPerson/login/start' \  -H 'Content-Type: application/json' \  -d '{  "email": "user@example.com",  "password": "string",  "tenantCode": "string",  "codeChallenge": "string"}'
Example Response
{  "nextStep": "token",  "sessionCode": "string"}

Register a patient POST

Registers a new patient account in a tenant and returns its tokens, so the user is signed in straight away. On some projects a business email address gets a clinician invite instead. **Auth:** none. The tenant is named by `tenantCode`. **Scope:** the project that owns `tenantCode`. ## Behaviour - Registration needs a default patient access policy on the project, and `PATIENT_REGISTRATION_ENABLED` must not be `false` (it defaults to on). The new membership gets that access policy. - The password must have at least 12 characters, not counting spaces at either end, and must not be on Ovok's list of common and breached passwords. Any character is allowed and none is required. A refused password answers 422 with the error on `password`. - An email that already has a Patient account in this project is refused. - **Clinician invite.** When the project setting `CLINICIAN_INVITE_ON_BUSINESS_EMAIL` is on and the address is a business address (not free-mail or disposable), no patient is created. Ovok creates a practitioner account with the project's default practitioner access policy, emails a `CLINICIAN_SIGNUP_INVITE` with a set-password link, and answers `{ "nextStep": "clinician-invite" }` (no tokens). If the invite cannot go out (no default practitioner policy, no practitioner app URL, the email fails), a patient is registered as usual. - The invite email carries a "continue as patient" link with a `continueAsPatientToken`. Send that token here to register as a patient anyway. It is valid for 7 days and only for the same email and project. - On success a `PATIENT_WELCOME` email is sent in the background. The response does not wait for it. - Error responses are delayed to take at least one second. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/auth/tenant/Patient/register' \ -H 'Content-Type: application/json' \ -d '{ "email": "max.mustermann@example.com", "password": "your-password", "name": "Max", "surname": "Mustermann", "tenantCode": "my-medical-project" }' ```

Exchange related person session code for tokens POST

Finishes a related person (carer) login: exchanges the session code from `login/start` (or `login/mfa`) and your PKCE `codeVerifier` for an access token and a refresh token. **Auth:** none. The session code and code verifier prove the earlier steps. ## Behaviour - Ovok redeems the code with Medplum's `oauth2/token` endpoint (`grant_type=authorization_code`). - The signed-in profile must be a RelatedPerson. A code for any other profile type is refused. - The token reads only what patients have shared with the carer: the shared Observation codes and each sharer's record with its contact fields hidden. Practitioner and patient-only routes refuse it with 403. - If the account was scheduled for deletion (`DELETE /auth/delete`), logging in cancels the deletion. - The response holds `accessToken`, `refreshToken`, `expiresIn` (seconds) and references to the `project` and `profile`. - Error responses are delayed to take at least one second. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/auth/tenant/RelatedPerson/login/token' \ -H 'Content-Type: application/json' \ -d '{ "sessionCode": "<sessionCode from login/start>", "codeVerifier": "<your codeVerifier>" }' ```