Signing people in

What your application calls to register, sign in, and stay signed in.

Stash runs an auth service for every project: your users, your passwords, your sessions. It is the same service a migration brings your existing users into, with their passwords intact.

This page is what your application has to call.

What moves and what changes

If you came from another platform, this is the one part of your application that needs editing.

Your queries Work unchanged. Point your client at the URL and key on your project's overview and carry on.
Your sign-in code Changes. It calls Stash's auth instead, which is a handful of call sites rather than every query.

The reason is not a missing feature. Stash's auth is its own service with its own API, and pretending to be somebody else's would mean matching their endpoints, their token format and their error shapes forever, including for applications that never used them. If that trade is blocking you, say so and it can be revisited.

Where it is

Every project has its own auth service, at its own address:

https://your-stash/api/auth/projects/<projectId>

Your project's id is in the address bar when you open it in the dashboard. On a local Stash the whole thing looks like this:

http://127.0.0.1:3010/api/auth/projects/2f7c1b6a-0000-4000-8000-000000000001

Sessions are per project. A token from one project is not accepted by another, and neither is a Stash dashboard login: your users are not Stash users.

Registering somebody

const auth = 'http://127.0.0.1:3010/api/auth/projects/<projectId>'

const response = await fetch(`${auth}/sign-up/email`, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ name: 'Ada', email: 'ada@example.com', password: 'a passphrase' }),
})
const { token } = await response.json()

Signing in

const response = await fetch(`${auth}/sign-in/email`, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ email: 'ada@example.com', password: 'a passphrase' }),
})
const { token } = await response.json()

Keep that token. It is what says which of your users a later request belongs to.

Using it with your data

Send it as a header alongside your project key:

await fetch(`${dataUrl}/rest/v1/orders?select=*`, {
  headers: {
    apikey: STASH_KEY,
    authorization: `Bearer ${token}`,
  },
})

A header rather than a cookie, because your application is on your own domain and a cross-site request carries no cookie.

This is the part that matters for row level security. With the header, the query runs as that person and auth.uid() is their id, so policies written against the signed-in user work exactly as they did before. Without it the query runs anonymously, which is correct for a public read and is why a page that shows nothing to a signed-in user is almost always a missing header.

Checking who somebody is

const response = await fetch(`${auth}/get-session`, {
  headers: { authorization: `Bearer ${token}` },
})
const session = await response.json()

An expired or unknown token is not an error. It answers with no session, because "nobody is signed in" is an ordinary state and your application has to render something either way.

Signing out

await fetch(`${auth}/sign-out`, {
  method: 'POST',
  headers: { authorization: `Bearer ${token}` },
})

Passwords that came from somewhere else

A migration brings your users across with their password hashes, so everybody signs in with the password they already had and nobody gets a reset email. The first time each person signs in, Stash quietly rehashes their password with its own algorithm. They never notice, and nothing about it can fail their sign-in.

The migrate screen names anybody who could not come across before it writes anything, so you know in advance rather than hearing about it from them.

What is not here yet

Social sign-in, magic links and one-time codes. Email and password is what a migration brings across and what these endpoints cover. If you need one of the others, that is worth saying out loud rather than discovering here.

Found something wrong? Edit this page.