# Add sign-in to a browser app without a backend

Seige adds sign-in to a static or frontend-only web app without an
authentication server. Users sign in with their Seige account in a Seige
window. Your app does not register a client ID, host a callback page, store a
client secret or handle passwords and tokens itself. Seige identifies the app
by the website it runs on.

```js
import { createSeige } from "@seige_sdk/sdk";

const seige = createSeige({ appName: "Habit tracker" });

signInButton.onclick = async () => {
  const { data: user, error } = await seige.auth.signIn();
  if (error) return showMessage(error.hint ?? error.message);
  showSignedIn(user.id);
};

const { data: current } = await seige.auth.user(); // null when signed out
```

## How the sign-in works

`seige.auth.signIn()` opens a Seige window. The user signs in to Seige if
needed and approves the connection to your app, then the call resolves with the
user. `seige.auth.user()` returns the signed-in user, or `null`, and never opens
a window. `seige.auth.signOut()` ends the session in this browser and keeps the
user's data.

You do not need to call `signIn()` before using data. The first database, file
or AI call that needs the user opens the same window and continues after
approval. Approval is remembered in that browser, so reloads do not ask again.

- `user.id` is specific to your website. Two different apps see different IDs
  for the same person, which prevents apps from linking users by ID.
- Call `seige.auth.signIn({ email: true })` to ask for the user's Seige email
  address. The approval window shows the request to the user.
- If the user closes the window, the call returns `SIGN_IN_CANCELLED`. If they
  decline, it returns `ACCESS_DENIED`.

## Security properties

Seige uses OAuth with pushed authorization requests, PKCE and DPoP-bound
tokens. Refresh tokens rotate on every use, and a reused refresh token revokes
that browser's authorization. Seige returns the sign-in result only to a window
on your app's website. Passwords are never sent to Seige's servers in readable
form; account sign-in uses the OPAQUE password protocol.

Code running on your website can use the session, so protect the app against
cross-site scripting as you would with any browser session.

## Storage comes with the sign-in

The same connection gives your app an encrypted folder in the user's account
for a [database](/guides/database-for-frontend-only-apps/) and
[files](/guides/file-storage-for-browser-apps/). Use it or ignore it; sign-in
works either way.

## Requirements

- An ES-module bundler that supports module workers and WebAssembly. Vite 5 to
  8, Next.js 16 and webpack 5 work without configuration.
- HTTPS in production. `http://localhost` works for development.
- Each user needs a Seige account. Account creation is currently open to
  invited usernames.

## Related guides

- [Instructions for coding agents](/guides/backend-for-coding-agents/)
- [Developer documentation](/developers/)
- [How Seige protects account data](/security/)
