> ## Documentation Index
> Fetch the complete documentation index at: https://docs.musterbox.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Player login, token refresh, and logout through the MusterBox SDK.

Authentication exchanges player credentials for a backend session. The SDK
stores and rotates the tokens for you — your game never reads or verifies
JWT signatures. The backend is the identity owner.

## Login

```rust theme={"dark"}
use musterbox_session::contract::LoginRequest;

let request = LoginRequest::new("player@example.com", "secret")
    .with_defaults(&auth_defaults); // device_id, device_name, device_os...

let success = sdk.authenticate(request)?;
// success.credentials, success.user, success.requires_otp
```

Browser:

```ts theme={"dark"}
await box.authenticate({
  identifier: "player@example.com",
  password: "secret",
});
```

Under the hood this calls `POST /api/v1/user/login` and returns:

| Field          | Meaning                                                                                  |
| -------------- | ---------------------------------------------------------------------------------------- |
| `accessToken`  | Bearer access token used for subsequent calls                                            |
| `refreshToken` | Rotated at `/api/v1/auth/validate`                                                       |
| `expiresIn`    | Access-token lifetime in seconds                                                         |
| `user`         | Backend user object                                                                      |
| `requiresOTP`  | When `true`, the SDK fails with `AuthenticationFailed` — OTP flows are not yet supported |

## Token lifetime

Token lifetime is derived from the backend `expiresIn` value and, when
present, from JWT `exp` claims with clock-skew grace. The refresh-token
fallback lifetime is **7 days** when the backend omits expiry and the token
is not a decodable JWT.

## Refresh

The SDK refreshes automatically near expiry. Manual rotation:

```rust theme={"dark"}
let creds = sdk.refresh_session()?;
```

## Logout

Revokes the server session (`POST /api/v1/user/s/logout`, body
`{ "device_id": ... }`) and clears local credentials.

```rust theme={"dark"}
sdk.logout()?;
```

## Device metadata

Login requests can carry device context through \[auth defaults]:

```rust theme={"dark"}
let mut defaults = AuthDefaults::default();
defaults.device_id = Some(device_id());
defaults.device_name = Some("Arcade Cabinet");
defaults.device_os = Some("macOS");
sdk.configure_auth_defaults(defaults);
```

`device_id` is also sent as the `x-device-id` header on login.

## Security notes

<Warning>Never log tokens, passwords, or PINs.</Warning>

* Treat `SessionNotAuthenticated` as "re-authenticate" — never fall back to
  unauthenticated privileged calls.
* The SDK supports identifier+password credentials today; OTP-based
  verification is surfaced as an error until supported client-side.

Next: [Sessions](/sdk/sessions).
