# Authentication

Canonical page: https://docs.ovok.com/flutter-sdk/authentication

`ovok.auth` signs users in to the configured tenant and keeps their session in the
secure store.

## Sign in [#sign-in]

```dart
final result = await ovok.auth.login(
  profileType: ProfileType.patient,
  email: email,
  password: password,
);

switch (result) {
  case SignedIn():
    break;
  case MfaRequired(:final challenge):
    await ovok.auth.verifyMfa(challenge, code);
}
```

`login` runs the tenant login with PKCE. Social sign-in uses
`socialLogin(SocialProvider.google, internalId: ..., credential: {...})` and needs the
`clientId` option.

## Register [#register]

`register(Registration(...))` returns `SignedIn`, or `ClinicianInvite` when the
project routes that email to a clinician invitation. `registerPractitioner` creates a
practitioner account.

## How the session behaves [#how-the-session-behaves]

- **Storage:** one JSON value under `ovok:<tenantCode>:session`, in the shape
  `@ovok/core/next` writes. A read that throws, such as before the first unlock,
  counts as "no session"; the client never deletes anything because a read failed.
- **Refresh:** access tokens refresh a minute before they expire. Concurrent requests
  share one refresh.
- **Refused refresh:** the user is signed out and `onUnauthenticated` is called. An
  outage keeps the session so a later call can retry.
- **401:** the request refreshes once and is sent once more.
- **Logout:** `logout()` always clears the local session, even offline.

## Account and sessions [#account-and-sessions]

- `current()` returns the stored session; `me()` reads the signed-in profile.
- `changePassword`, `resetPassword` and `completePasswordReset` manage passwords;
  `deleteAccount(days: 30)` schedules account deletion.
- `sessions.list()` lists the user's sessions, and
  `sessions.revoke('current' | 'other' | 'all' | sessionId)` ends them.
