> For the complete documentation index, see [llms.txt](https://docs.baas.sh/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.baas.sh/baas-sdk/authentication/sessions.md).

# Sessions

After a user signs in, the SDK holds a **session**. This guide covers reading it, reacting to changes, and ending it.

## Read the current session

`getSession()` returns the session synchronously, or `null` if signed out.

```ts
const session = baas.auth.getSession();
if (session) {
  console.log('User:', session.address);
}
```

```ts
type BaasSession = {
  address:     string;               // checksummed EVM address (0x…)
  accessToken: string;               // raw JWT — attach as `Authorization: Bearer <token>`
  expiresAt:   number;               // Unix timestamp in SECONDS (matches the JWT `exp`)
  method?:     'passkey' | 'wallet'; // sign-in method (used by baas.wallet to route the default signer)
};
```

Because `createBaasClient()` is **synchronous** and restores the session from `localStorage` as it's created, `getSession()` returns the right value on the **first render**, with no loading flash for an already-signed-in user, even after a page refresh.

## React to changes

`onAuthStateChange()` fires **immediately** with the current state, then on every change (sign-in, sign-out, refresh). Use it to keep your UI in sync.

```ts
const unsubscribe = baas.auth.onAuthStateChange((session) => {
  if (session) {
    // user is signed in
  } else {
    // user is signed out
  }
});

// Later — stop listening
unsubscribe();
```

{% hint style="info" %}
**Sessions are synced across tabs.** A sign-in or sign-out in one tab is reflected in every other open tab, and `onAuthStateChange` fires accordingly. No extra setup required.
{% endhint %}

## Sign out

```ts
await baas.auth.signOut();
```

`signOut()` clears the local session, notifies your `onAuthStateChange` listeners with `null`, and asks the server to clear its refresh cookie. It always succeeds, even if the server is unreachable.

{% hint style="info" %}
**The passkey is preserved.** Signing out keeps the user's passkey on file, so the next sign-in needs a single prompt instead of two. Already-issued access tokens stay valid until they expire (standard JWT behaviour), and the server-side refresh cookie is cleared so no new tokens can be issued.
{% endhint %}

## Security model

It's worth understanding where tokens live:

* The **refresh token** is stored in a `Secure; HttpOnly; SameSite` **cookie** set by the server, unreachable from JavaScript.
* The **access token** is kept in `localStorage` (under `baas_session_<projectId>`). It's a short-lived JWT, so an XSS that steals it is bounded by the token's lifetime, usually under an hour.

It's a deliberate trade-off: `localStorage` is simple and sufficient for short-lived access tokens, and the long-lived secret (the refresh token) stays out of JavaScript's reach.

## Sending the token to your own backend

`session.accessToken` is a standard JWT. If you have your own backend, you can forward it to identify the user.

```ts
await fetch('https://my-api.example.com/me', {
  headers: { Authorization: `Bearer ${baas.auth.getSession()?.accessToken}` },
});
```

Your backend verifies the JWT as it would any bearer token.

<details>

<summary>Advanced — forcing a fresh token with <code>refresh()</code></summary>

The SDK already refreshes the access token automatically before any authenticated request when it's within 60 seconds of expiry, so **most apps never need to call `refresh()` directly.**

Call it explicitly only when you need a guaranteed-fresh token to forward somewhere that won't trigger the automatic path:

```ts
const accessToken = await baas.auth.refresh();
```

Concurrent calls share a single in-flight request, so calling it many times in parallel results in one network call. It throws `SESSION_EXPIRED` if the refresh cookie is no longer valid (the user must sign in again). See [Error handling](/baas-sdk/resources/error-handling.md).

</details>

## Next

* [Use with React](/baas-sdk/integrations/react.md) — turn `onAuthStateChange` into a hook.
* [Manage user](/baas-sdk/manage-user.md) — update the signed-in user's email and push tokens.
* [Error handling](/baas-sdk/resources/error-handling.md) — handle expired sessions and refresh failures.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.baas.sh/baas-sdk/authentication/sessions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
