Skip to contentSkip to navigation

Send authentication emails

Send authentication emails for magic-link sign-in, email verification, password resets, and organisation invitations through Own Auth Delivery.

Authentication email delivery

Own Auth Delivery sends magic-link sign-in, email-verification, password-reset, and organisation-invitation emails. Configure one server-only delivery key. The own-auth package still creates and verifies every token.

1. Create a Delivery account

Create a Delivery account and open the Own Auth dashboard. This is separate from the own-auth package because Delivery is a managed service with its own dashboard.

2. Create an app

Open App Settings and create an app. The app name should match the product because it appears in emails sent to its users.

4. Get your delivery key

Go to the Keys tab and create a delivery key. Copy the key because it's shown once.

.env
OWN_AUTH_EMAIL_DELIVERY_KEY=oad_...

5. Configure Own Auth

Configure Own Auth with the delivery key. Set baseUrl to the website or app URL used in authentication links.

auth.ts
import { Pool } from "pg";
import { OwnAuthManagedEmailProvider, createOwnAuth } from "own-auth";
import { createPostgresAuthStorage } from "own-auth/postgres";

const pool = new Pool({
  connectionString: process.env.DATABASE_URL
});

export const auth = createOwnAuth({
  storage: createPostgresAuthStorage(pool),
  tokenPepper: process.env.OWN_AUTH_TOKEN_PEPPER,
  baseUrl: "https://app.example.com",
  emailProvider: new OwnAuthManagedEmailProvider({
    deliveryKey: process.env.OWN_AUTH_EMAIL_DELIVERY_KEY
  })
});

Send each authentication email type

request-magic-link.ts
await auth.requestMagicLink({
  email: "user@example.com",
  redirectUrl: "/dashboard"
});
Own Auth methodEmail
requestMagicLinkMagic-link sign in
requestEmailVerificationEmail verification
requestPasswordResetPassword reset
inviteMemberOrganisation invitation

What Delivery does

Delivery:

  • Receives the email request from the own-auth package running in your backend.
  • Sends the email with the auth link.
  • Queues and retries on temporary failures.
  • Logs the delivery status (accepted, delivered, failed).

What Delivery does not do

Delivery does not:

  • Create users.
  • Verify tokens.
  • Create sessions.
  • Touch your database.
  • Store your user data.
  • Make auth decisions.

Your backend runs own-auth, which creates the token and builds the auth URL. Delivery receives that URL and sends it in an email. The own-auth package in your backend does all the auth work.

Local Development

A delivery key works in local development and sends real emails. Delivery does not provide a sandbox mode. Use a local mail catcher through a custom email provider when development messages should remain on the local machine.

Use Your Own Email Provider

To stop using Delivery, replace OwnAuthManagedEmailProvider with your own EmailProvider. Its send method calls your email service or SMTP server.

auth.ts
import { createOwnAuth, type EmailProvider } from "own-auth";

const emailProvider: EmailProvider = {
  async send(message) {
    await emailClient.send({
      from: "My App <no-reply@example.com>",
      to: message.to,
      subject: "Continue to My App",
      html: `<a href="${message.url}">Continue</a>`
    });
  }
};

export const auth = createOwnAuth({
  tokenPepper: process.env.OWN_AUTH_TOKEN_PEPPER,
  baseUrl: "https://app.example.com",
  emailProvider
});

Production check

Send one test message for each enabled flow. Check Delivery logs for accepted, delivered, and failed states. Use Hosted Links for a managed website or app bridge. Review Delivery security before production.