Skip to content

Authentication

HostEdge Auth adds sign-in to an app that runs on HostEdge. Your users live in your project database, so they never leave your project and you can query them with SQL. It works in a Worker or the server side of a framework.

It covers:

  • email and password, with sessions
  • magic links (sign in from an emailed link)
  • password reset
  • optional email confirmation
  • sign-in with Google or GitHub
  • rate limits that slow down guessing and email abuse

Set it up#

  1. Open Project › Storage and open a SQL database (add one if you have none).
  2. In the Authentication panel choose Set up authentication. This creates the auth_* tables.
  3. Download hostedge-auth.ts from the panel, or fetch it from https://hostedge.app/auth-kit/hostedge-auth.ts, and put it in your project. It is one file with no dependencies.
  4. Use it in your Worker, then redeploy:
import { createAuth } from './hostedge-auth'

export default {
  async fetch(request, env) {
    const auth = createAuth(env.DB, { env })
    const response = await auth.handle(request) // everything under /auth/…
    if (response) return response

    const user = await auth.getUser(request) // { id, email } or null
    if (!user) return new Response('Sign in first', { status: 401 })
    return new Response(`Hello ${user.email}`)
  },
}

Pass env so HostEdge can send your emails (see below). The panel also lists the people who signed up, with Sign out everywhere, Disable and Delete for each.

Endpoints#

auth.handle(request) answers these. POSTs take a JSON body and must send content-type: application/json, which also protects them from cross-site forms.

RequestWhat it does
POST /auth/sign-up { email, password }Creates the account and signs in (or sends a confirmation)
POST /auth/sign-in { email, password }Signs in
POST /auth/sign-outEnds this browser's session
GET /auth/me{ user }, or { user: null }
POST /auth/magic-link { email, next? }Emails a one-time sign-in link (creates the account if new)
GET /auth/verify?token=…&next=/The link in that email: signs in and redirects to next
POST /auth/reset-request { email }Emails a password reset link
POST /auth/reset { token, password }Sets the new password, signs out other devices, signs in
GET /auth/oauth/github and /auth/oauth/googleStarts sign-in with the provider

Passwords need at least 8 characters. next only accepts paths on your own site.

The reset email links to /reset-password?token=… on your site. Build that page: a form that sends the token and a new password to POST /auth/reset.

Emails#

HostEdge sends the magic-link, reset and confirmation emails for you, from its own sender and with your project's name, so there is nothing to set up. Every deploy adds HOSTEDGE_PROJECT_ID, HOSTEDGE_MAIL_URL and HOSTEDGE_MAIL_SECRET to your Worker; passing env to createAuth is all it takes.

PlanAuth emails per day, per project
Free50
Starter500
Pro2,000
Agency10,000

One address receives at most 5 emails an hour from a project, and links can only point at your project's own addresses.

To send them yourself (Resend, Postmark, anything), pass a function instead:

createAuth(env.DB, {
  sendEmail: async ({ to, kind, url }) => {
    // kind is 'magic_link', 'reset' or 'confirm'
    await myMailer.send({ to, subject: 'Your link', text: url })
  },
})

Confirm emails#

Add confirmEmail: true to make people click an emailed link before they can sign in with a password. Until then, sign-in answers email_not_verified.

Google and GitHub#

Create an OAuth app with the provider and give it this redirect address:

https://your-site.example/auth/oauth/github/callback
https://your-site.example/auth/oauth/google/callback

Store the client ID and secret as environment variables and pass them in:

createAuth(env.DB, {
  env,
  oauth: {
    github: { clientId: env.GITHUB_ID, clientSecret: env.GITHUB_SECRET },
    google: { clientId: env.GOOGLE_ID, clientSecret: env.GOOGLE_SECRET },
  },
})

Link people to /auth/oauth/github?next=/dashboard. Only a provider's verified email is accepted, and signing in with a provider uses the same account as a magic link or password for that email.

Security notes#

  • Passwords are hashed with PBKDF2 (SHA-256, 100,000 iterations, the most a Worker allows). Session tokens are stored hashed, in an HttpOnly, Secure, SameSite=Lax cookie.
  • After 10 wrong passwords for an email, or 50 from one address, sign-in is locked for 15 minutes. Requests for links, resets and sign-ups are limited per email and per address.
  • Password reset gives the same answer and timing whether or not the account exists, so the form can't be used to find out who has an account.
  • If someone registers an email with a password and its real owner later proves the address (magic link, Google or GitHub), the earlier password is discarded.

Errors#

Failures return JSON like { "error": "invalid_credentials" } with a matching status: invalid_email and weak_password (400), email_taken (409), invalid_credentials (401), too_many_attempts (429), disabled and email_not_verified (403), email_unavailable (503), invalid_token and oauth_failed (400).

Limits#

HostEdge Auth keeps its tables in your project database, so users count toward your storage and request allowances like any other data. It suits apps up to a few thousand concurrent users; see Databases and storage for connecting your own Postgres when you outgrow that.

View this page as MarkdownAll docs as one file