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.
3. Configure link mode
In the Settings tab, under Link mode, choose how auth links in emails should work.
| Mode | Behavior |
|---|---|
| My URLs | Links point directly to the configured website, localhost, or app URL. At least one Allowed URL is required. Add every accepted website root or app scheme. |
| Own Auth hosted | Links point to go.own-auth.com before continuing to the website or app destination saved in Settings. Set the destination URL and an optional fallback URL. |
See Hosted Links for hosted-link setup.
4. Get your delivery key
Go to the Keys tab and create a delivery key. Copy the key because it's shown once.
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.
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
await auth.requestMagicLink({
email: "user@example.com",
redirectUrl: "/dashboard"
});| Own Auth method | |
|---|---|
| requestMagicLink | Magic-link sign in |
| requestEmailVerification | Email verification |
| requestPasswordReset | Password reset |
| inviteMember | Organisation invitation |
What Delivery does
Delivery:
- Receives the email request from the
own-authpackage 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.
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.