# Authentication and Organizations

Better Auth owns identity, sessions, Organizations, platform roles and OAuth.

## Session outcomes [#session-outcomes]

Password sign-in can return a Session, a pending two-factor challenge, an unverified email, a Ban or a refusal. Treat those as distinct outcomes. `session-outcome.ts` and `two-factor-outcome.ts` provide the shared interpretation; hooks own navigation and error presentation.

The server registers two-factor, admin, organization, passkey, Expo and MCP OAuth plugins. Email verification policy comes from `AUTH_SKIP_EMAIL_VERIFICATION`; setup makes the intended policy explicit. Current server authorization reads the database, with cookie caching disabled.

## Organizations and roles [#organizations-and-roles]

Signup provisions a personal Organization. A User may be a Member of several Organizations; the Session selects one Active Organization. Todos and files belong to that Organization. Platform role `admin` grants global administration; Org roles `owner`, `admin` and `member` do not grant platform administration.

Membership must be checked at the operation, even if the UI already selected an Organization. An MCP token has no active selection and stays pinned to the User's personal Organization. See [connecting agents](/docs/connect-your-agent).

## Web and native [#web-and-native]

Web auth hooks coordinate TanStack Query, forms and redirects. Mobile uses the Better Auth Expo client, secure credential storage and native passkey integration. Its route gate revalidates the Session and hides private content during a transition. Logout, expiry or an authoritative 401 clears private state. A 403 does not automatically sign out an otherwise valid Session.

## Extend safely [#extend-safely]

Add auth behavior to the server factory and its tests, then expose the outcome through a hook. Keep email callbacks, membership checks and audit recording in their existing owners. Test revoked Sessions and Organization changes as well as successful login. Never treat an impersonated admin's original identity as permission to access `/admin`.


## Key files [#key-files]

- [`packages/auth/src/index.ts`](https://github.com/CarlosZiegler/doro/blob/main/packages/auth/src/index.ts)
- [`packages/auth/src/session-outcome.ts`](https://github.com/CarlosZiegler/doro/blob/main/packages/auth/src/session-outcome.ts)
- [`packages/db/src/provision-organization.ts`](https://github.com/CarlosZiegler/doro/blob/main/packages/db/src/provision-organization.ts)
- [`apps/web/src/hooks/use-sign-in.ts`](https://github.com/CarlosZiegler/doro/blob/main/apps/web/src/hooks/use-sign-in.ts)
- [`apps/mobile/src/hooks/use-session-lifecycle.ts`](https://github.com/CarlosZiegler/doro/blob/main/apps/mobile/src/hooks/use-session-lifecycle.ts)

