Authentication

DSN credentials for ingest; session cookies for /api/v1. They are not interchangeable.

Epure uses two auth mechanisms.

What is DSN vs session?

The DSN authenticates ingest. Dashboard /api/v1/* uses a session cookie and RLS app.current_org_id.

SurfacePathsCredentialScope
Ingest/api/{project_id}/envelope/, /store/, /releases/…/files/, /user-feedback/DSN public + secret keyProject (and parent org) from the key
Dashboard/api/v1/* (except public auth routes)Session cookieOrg from session; RLS app.current_org_id

Sending a session cookie to ingest does nothing. Sending DSN headers to /api/v1/issues returns 401 { "error": "unauthenticated" }.

How does DSN ingest auth work?

Credentials come from a project DSN key. Create or rotate one in the UI, or via /api/v1/projects/{id}/dsn-keys.

Preferred outside browser SDKs:

X-Sentry-Auth: Sentry sentry_version=7, sentry_key={public_key}, sentry_secret={secret_key}

Secret comparison is constant-time.

DSN URL shape

http://{public_key}:{secret_key}@{host}/{project_id}

or public-key-only forms depending on the SDK. The path {project_id} must match the key’s project.

StatuserrorWhat to do
403project_mismatchUse the project UUID from the DSN
403dsn_revokedCreate or rotate a key
401invalid_dsnCheck sentry_key / header spelling

CORS

Ingest routes answer OPTIONS for browser SDKs. Allowed request headers include X-Sentry-Auth, Content-Type, Content-Encoding. Origins: Configuration.

How does session auth work?

After password or Google login, the server sets an HttpOnly cookie backed by Postgres tower-sessions.

ModeCookie name
Secure (EPURE_SESSION_SECURE=1, default prod)__Host-epure.sid
Local HTTP (EPURE_SESSION_SECURE=0)Epure.sid

Attributes: HttpOnly, SameSite=Lax, Path=/, inactivity expiry 14 days.

No bearer tokens in localStorage.

Login

curl -sS -c cookies.txt -D - -o /dev/null -X POST \
  "http://localhost:8080/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"dev@epure.local","password":"devpassword"}'
ResultMeaningWhat to do
204 + Set-CookieSession establishedReuse -b cookies.txt on /api/v1/*
401Bad email/passwordCheck seed user or register
429 plain text20 req / IP / 60sWait

Public /api/v1/auth routes

MethodPathNotes
GET/api/v1/auth/config{ google_enabled, password_enabled }
POST/api/v1/auth/registeremail + password (+ optional invite_token)
POST/api/v1/auth/loginemail + password → 204
GET/api/v1/auth/googleOIDC start
GET/api/v1/auth/google/callbackOIDC callback
GET/api/v1/auth/mecurrent session (requires cookie)
POST/api/v1/auth/logoutclear session
POST/api/v1/auth/accept-invitation{ invite_token }
PATCH/api/v1/auth/profile{ display_name }
PATCH/api/v1/auth/passwordchange password
DELETE/api/v1/auth/accountdelete account

Login body:

{ "email": "you@example.com", "password": "your-password", "invite_token": null }
Login succeeds but later /api/v1 calls are 401?

The browser rejected the cookie over an HTTPS vs EPURE_SESSION_SECURE mismatch. Local HTTP needs 0 (Epure.sid); HTTPS needs 1 (__Host-epure.sid). DSN headers on this path also return 401, so use the cookie. See Troubleshooting.

Can I use the DSN as a bearer token?

No, and there are no bearer tokens in localStorage either. The DSN covers ingest only: envelope, store, release files, user feedback. Issues and Events need the login cookie. The tables above list which header belongs on which path.