1---
2title: Production Auth
3description: Configure trusted origins, SMTP, OAuth callbacks, and verification before launching Managed Better Auth.
4---
5
6Prepare external email and OAuth services before taking Managed Better Auth to
7production. Alchemy configures Neon; it does not create an OAuth application at
8GitHub/Google or verify an email-sending domain for your SMTP provider. Start with
9[Setup](/neon/setup) and Neon's
10[production checklist](https://neon.com/docs/auth/production-checklist).
11
12The snippets below run inside a stack and refer to an existing `branch`.
13Configure an Alchemy-owned Auth instance through code; avoid managing the same
14settings independently in the Console. An existing or inherited Auth integration
15requires deliberate, resource-scoped adoption and review of its users and settings.
16
17## Set the application name
18
19```typescript
20import * as Neon from "alchemy/Neon";
21
22const auth = yield* Neon.Auth("Auth", {
23 branch,
24 name: "Example App",
25});
26```
27
28The name appears in user-facing Auth messages. Keep the logical resource ID
29stable when adding the settings below.
30
31## Register the production origin
32
33```typescript
34const origin = yield* Neon.AuthTrustedDomain("AppOrigin", {
35 auth,
36 domain: "https://app.example.com",
37});
38```
39
40Use the application's exact origin, including scheme and port when applicable,
41not an OAuth callback path. Declare each intended production origin separately.
42A trusted origin is neither a DNS record nor a Function custom domain; set up the
43latter using [Custom domains](/neon/guides/custom-domains).
44
45## Prepare an email sender
46
47In your email provider, verify the sender/domain and complete its required DNS
48verification before configuring Neon. Obtain the SMTP host, port, username,
49password, and approved sender address. Store the password in your deployment
50secret configuration as `AUTH_SMTP_PASSWORD`; keep it out of browser environment
51variables and source control.
52
53Neon's shared SMTP service is intended for development. Production delivery and
54verification links require your own provider; see
55[Neon's email-provider requirements](https://neon.com/docs/auth/production-checklist#email-provider).
56Use the port and credentials supplied by that provider rather than assuming a
57particular SMTP transport.
58
59## Configure SMTP
60
61Add the email provider to the existing Auth declaration:
62
63```diff lang="typescript"
64+import * as Config from "effect/Config";
65
66 const auth = yield* Neon.Auth("Auth", {
67 branch,
68 name: "Example App",
69+ emailProvider: {
70+ type: "standard",
71+ host: "smtp.example.com",
72+ port: 587,
73+ username: "smtp-user",
74+ password: yield* Config.Redacted("AUTH_SMTP_PASSWORD"),
75+ sender_email: "auth@example.com",
76+ sender_name: "Example App",
77+ },
78 });
79```
80
81Replace the SMTP example values with the verified provider settings. The password
82is redacted in the resource properties; protect the state store that retains it.
83
84## Enable email verification
85
86```diff lang="typescript"
87 const auth = yield* Neon.Auth("Auth", {
88 branch,
89 name: "Example App",
90+ emailAndPassword: {
91+ enabled: true,
92+ require_email_verification: true,
93+ },
94 emailProvider: {
95```
96
97This requires verification for email/password sign-in. It does not verify existing
98mailboxes for you. Test receipt and completion of the verification flow with a
99fresh test user after deploying.
100
101## Disable localhost access
102
103```diff lang="typescript"
104 const auth = yield* Neon.Auth("Auth", {
105 branch,
106 name: "Example App",
107+ allowLocalhost: false,
108```
109
110Keep local development on a separate branch with its own explicit settings.
111Removing the property is not the same as setting it to `false`: unspecified Auth
112settings are preserved, and removal of previously managed settings can require an
113explicit reset value.
114
115## Register an OAuth application
116
117If you use social sign-in, create your own OAuth application at the provider.
118For example, follow GitHub's
119[OAuth app instructions](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app).
120Keep its client secret in deployment secret configuration as
121`GITHUB_CLIENT_SECRET`.
122
123In Neon, select the project's intended branch and open **Settings → Auth → OAuth
124providers**. The provider configuration dialog shows the exact authorization
125callback URL. Copy it to the OAuth provider's allowed redirect configuration;
126use the dialog to inspect the URL, while leaving Alchemy responsible for saving
127the Neon provider configuration.
128
129The callback has this shape:
130
131```text
132{NEON_AUTH_BASE_URL}/callback/github
133```
134
135Use the branch's Auth base URL, not the Function URL or application homepage.
136The app's `callbackURL` is a different value: it is where the user lands after
137Auth completes, and its origin must be trusted. See
138[Neon's OAuth guide](https://neon.com/docs/auth/guides/setup-oauth) for Google,
139GitHub, and Vercel instructions, including consent-screen publication and provider
140verification requirements.
141
142## Bind the OAuth credentials
143
144```typescript
145const github = yield* Neon.AuthOAuthProvider("GitHub", {
146 auth,
147 provider: "github",
148 clientId: "your-oauth-client-id",
149 clientSecret: yield* Config.Redacted("GITHUB_CLIENT_SECRET"),
150});
151```
152
153Neon-managed development credentials are not a production identity for your
154application. An already configured provider requires scoped adoption before
155Alchemy manages it. Each preview branch has a different Auth URL; register its
156callback separately and use a separate OAuth application when the provider only
157allows one callback. Never redirect preview sign-ins through production Auth as
158a shortcut.
159
160## Verify the complete sign-in flow
161
162Use the real production hostname with a designated test user:
163
1641. Sign up and receive the verification email. Confirm an unverified account
165 cannot bypass the verification requirement.
1662. Complete verification and sign in. Refresh and confirm the session behaves as
167 expected.
1683. Request a password reset and follow the email back to the intended origin.
1694. If OAuth is enabled, sign in through the provider and confirm both redirects:
170 provider → branch Auth callback → application.
1715. Sign out and verify protected requests are rejected. Account for the expiry of
172 already-issued JWTs; session revocation is not necessarily immediate JWT invalidation.
1736. Confirm an untrusted origin and localhost are rejected by production Auth.
174
175Functions still need application-level authentication and authorization. Validate
176JWT signatures, issuer, audience where applicable, and expiry; Data API calls
177must carry the end user's token and be governed by SQL grants and row-level
178security. A trusted origin does not protect a public Function by itself.
179
180## Troubleshoot before launch
181
182| Symptom | Check |
183| --- | --- |
184| OAuth `redirect_uri_mismatch` | The provider's redirect is the selected branch's Auth URL plus `/callback/<provider>`, not the app's post-login URL |
185| Sign-in only works for the OAuth app owner | Provider testing mode, approved test users, consent-screen publication, and verification |
186| Email missing or rejected | Verified sender, SMTP credentials/port, provider delivery logs, spam folder, and rate limits |
187| Redirect rejected | Exact application origin in trusted domains, correct branch, and no production dependency on localhost |
188| Auth was disabled outside Alchemy | Preserve `neon_auth` and state; use [State and recovery](/neon/guides/state-recovery) rather than dropping user data to re-enable it |
189
190## Related guides
191
192- [Setup](/neon/setup) — credential and account prerequisites.
193- [Auth reference](/providers/neon/auth) — supported settings and lifecycle.
194- [Upload tutorial](/neon/tutorial) — development application and its production limits.