Authentication
Learn how to set up and use authentication with Better Auth in MinuteShip
MinuteShip uses Better Auth for authentication, a TypeScript-native authentication library.
Setup
Environment Variables
Generate a random secret and add it to your environment variables file:
openssl rand -base64 32
.env
BETTER_AUTH_SECRET=your_generated_secret
Website Configuration
In most cases, the default configuration works fine. If you need to change it, modify the auth config in src/config/website.ts:
export const websiteConfig: WebsiteConfig = {
// ...
auth: {
enable: true,
enableGoogleLogin: true, // Enable Google login
enableCredentialLogin: true, // Enable email/password login
enableDeleteAccount: true, // Allow users to delete their account
},
// ...
};
| Option | Type | Default | Description |
|---|---|---|---|
| enable | boolean | true | Enable/disable authentication |
| enableGoogleLogin | boolean | true | Enable Google OAuth login |
| enableCredentialLogin | boolean | true | Enable email/password login |
| enableDeleteAccount | boolean | true | Allow users to delete their account |
Google OAuth (Optional)
If Google login is enabled, you need to configure Google OAuth:
- Go to Google Cloud Console
- Create a new project
- Go to APIs & Services > Credentials
- Click Create Credentials > OAuth client ID
- Configure the consent screen if prompted
- Select Web application as the application type
- Add
http://localhost:3000andhttps://your-domain.comto Authorized JavaScript origins - Add
http://localhost:3000/api/auth/callback/googleandhttps://your-domain.com/api/auth/callback/googleto Authorized redirect URIs - Copy the Client ID and Client Secret to your environment variables file:
.env
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
Note
If you are setting up your environment, you can now go back to the Environment Configuration and continue. The rest of this document can be read later.
- Environment Configuration: Set up environment variables
Google One Tap (Optional)
Google One Tap shows Google's account chooser to signed-out visitors, so they can sign in from any page without opening the login page first. It reuses the OAuth client configured above and turns on as soon as VITE_GOOGLE_CLIENT_ID is set.
.env
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
VITE_GOOGLE_CLIENT_ID=your_google_client_id
VITE_* values are compiled into the browser bundle at build time, so rebuild after changing them. The client ID is public and must match GOOGLE_CLIENT_ID.
The client options live in src/auth/client.ts:
oneTapClient({
clientId: clientEnv.VITE_GOOGLE_CLIENT_ID ?? '',
autoSelect: false,
cancelOnTapOutside: true,
}),
clientId: public OAuth client ID. An empty value skips the prompt.autoSelect: false: the visitor must confirm an account, so the prompt never signs anyone in silently.cancelOnTapOutside: true: clicking outside the prompt dismisses it.
The server plugin in src/auth/auth.ts is registered only when enableGoogleLogin, GOOGLE_CLIENT_ID, and GOOGLE_CLIENT_SECRET are all set. GoogleOneTap in the root layout prompts once per page load for visitors without a session, then redirects to /dashboard; if the prompt fails, the Google button on the login page still works.
To keep Google login but drop the prompt, unset VITE_GOOGLE_CLIENT_ID and rebuild.
Verification Emails and Production Secrets
Production requires a unique random BETTER_AUTH_SECRET of at least 32 characters. Environment validation rejects the default better-auth-secret and shorter values. Upload the secret to the Worker before release; see Deployment.
Signup success does not guarantee email delivery. Signup and unverified-login forms offer verification-email resend. Accepted requests start a 60-second button cooldown; delivery failures display an error and allow retrying. Verification and password-reset emails attempt delivery up to three times, 250 ms apart. Password reset returns the same response for missing accounts and send failures. Verify delivery and links in a real inbox separately; see Email.
Authentication Architecture
The authentication system in MinuteShip consists of the following components:
src/auth/auth.ts: Better Auth server configurationclient.ts: Better Auth client configurationtypes.ts: Authentication type definitions
components/auth/: Authentication related components
routes/auth/login.tsx: Login pageregister.tsx: Registration pageforgot-password.tsx: Forgot password pagereset-password.tsx: Reset password page
middlewares/auth-middleware.ts: Auth middlewareadmin-middleware.ts: Admin middleware
Auth Routes
MinuteShip provides the following authentication routes:
| Route | Description |
|---|---|
/auth/login | Login page |
/auth/register | Registration page |
/auth/forgot-password | Password reset request |
/auth/reset-password | Password reset form |
/auth/error | Error page |
References
Next Steps
Now that you understand how authentication works in MinuteShip, you might want to explore these related features:
- Email: Configure email services
- Payment: Configure payment providers
- Database: Configure database
- Deployment: Deploy to Cloudflare Workers