Integrate Auth0 with Bolt.new using either Universal Login (redirect-based, works in preview since the redirect is to Auth0's domain) or the @auth0/auth0-react SDK for embedded login. Create an Auth0 tenant and SPA application, configure callback URLs for both your Bolt preview and deployed domain, implement login/logout/profile, and protect API routes with access tokens. Universal Login is recommended — it sidesteps OAuth callback issues. Free tier: 7,500 MAU.
Add Enterprise Authentication to Your Bolt.new App with Auth0
Auth0 is the most widely used third-party authentication service, handling login for thousands of applications ranging from early-stage startups to Fortune 500 enterprises. It provides Universal Login (a hosted, customizable login page), social login for 30+ providers, multi-factor authentication, RBAC, and enterprise SSO — all without building authentication infrastructure from scratch. The free tier supports 7,500 monthly active users, making it accessible for new projects.
There are two main approaches to integrating Auth0 with a Bolt.new React application. Universal Login uses a redirect flow: the user clicks 'Login', is redirected to Auth0's hosted login page (auth.yourtenantname.auth0.com), authenticates, and is redirected back to your application with a callback URL. This approach works in Bolt's WebContainer preview because the redirect goes to Auth0's domain — a stable, externally accessible URL — not back to the ephemeral WebContainer URL. The @auth0/auth0-react SDK provides the hooks and components that manage this flow.
The second approach uses the Auth0 SPA SDK for embedded login popups or lock widgets. This also works with proper callback URL configuration. The key requirement for both approaches is registering all URLs — your Bolt preview URL, your local development URL, and your deployed domain — in Auth0's Allowed Callback URLs, Allowed Logout URLs, and Allowed Web Origins fields. API routes can be protected by validating the JWT access token that Auth0 issues after successful login.
Integration method
Auth0 integrates with Bolt.new through two approaches. Universal Login redirects users to Auth0's hosted login page, which works in Bolt's preview because the redirect leaves the WebContainer domain — Auth0 handles the login and returns the user via callback URL. The @auth0/auth0-react SDK provides an embedded login experience for deployed applications. API routes use the Auth0 Management API or validate JWT access tokens to protect server-side endpoints.
Prerequisites
- A free Auth0 account — create one at https://auth0.com/signup (no credit card required, includes 7,500 MAU)
- An Auth0 tenant created in your preferred region during signup
- A Single Page Application created in Auth0 Dashboard → Applications → Create Application → Single Page Web Application
- Your Auth0 Domain (shown in the application settings, looks like dev-xxxxxx.us.auth0.com) and Client ID
- A Bolt.new account with a Next.js project open
Step-by-step guide
Create an Auth0 SPA Application and Configure Callback URLs
Create an Auth0 SPA Application and Configure Callback URLs
In the Auth0 Dashboard, go to Applications → Applications → Create Application → select 'Single Page Web Applications' → Create. Give it a name like 'Bolt Dev App'. In the application settings, you need to configure four URL fields that tell Auth0 where to redirect after login and logout, and which origins can make requests. Allowed Callback URLs: add all URLs where Auth0 should redirect after successful login. Include your Bolt preview URL (it looks like https://[hash].local.credentialless.webcontainer-api.io/), http://localhost:3000, and your deployed Netlify URL after deployment. Allowed Logout URLs: the same set of URLs where Auth0 should redirect after logout. Allowed Web Origins: add the same Bolt preview URL and localhost URL — this allows the auth SDK to make cross-origin requests. Allowed Origins (CORS): same values. The Bolt preview URL changes when you reload the project — if login stops working in a new session, the URL has changed. Add your deployed Netlify URL to the callback URLs immediately and use the deployed site for more reliable testing. Scroll down to 'Advanced Settings' → 'Grant Types' and confirm 'Authorization Code' and 'Implicit' are enabled. Copy your Domain and Client ID — you will add these as environment variables.
1# .env — add to project root2NEXT_PUBLIC_AUTH0_DOMAIN=dev-xxxxxxxx.us.auth0.com3NEXT_PUBLIC_AUTH0_CLIENT_ID=your_client_id_here4NEXT_PUBLIC_AUTH0_AUDIENCE=https://your-api-identifier5# Used server-side for Management API or JWT validation6AUTH0_CLIENT_SECRET=your_client_secret_herePro tip: The Auth0 Domain and Client ID are safe to expose with NEXT_PUBLIC_ prefix — they are public identifiers. Only the Client Secret must stay server-side. The audience is the API identifier you create in Auth0 API settings for issuing access tokens.
Expected result: Auth0 SPA application is created and callback URLs are configured. Environment variables are saved in the .env file.
Set Up Auth0Provider and Implement Login/Logout
Set Up Auth0Provider and Implement Login/Logout
Install the Auth0 React SDK with `npm install @auth0/auth0-react` in the Bolt terminal. The Auth0Provider component wraps your entire application and provides authentication context. In a Next.js App Router project, create a client-side providers wrapper and import it in your root layout. The Auth0Provider requires your domain and client ID, and an authorizationParams object with redirect_uri set to window.location.origin for the current URL. Using window.location.origin is better than a hardcoded URL because it automatically uses the correct domain in any environment — Bolt preview, local development, or Netlify production. The useAuth0 hook provides isAuthenticated, isLoading, user, loginWithRedirect, and logout. The login flow: user clicks login → loginWithRedirect() redirects to Auth0's hosted login page → user authenticates → Auth0 redirects back to your app at the redirect_uri → SDK exchanges the code for tokens → user is now authenticated. This entire flow works in Bolt's WebContainer because the actual OAuth redirect goes to Auth0's domain, not the WebContainer URL — Auth0 returns the user to whatever redirect_uri was in the request, which the SDK sets to window.location.origin.
Add Auth0 authentication to this Next.js project. Install @auth0/auth0-react. Create a client-side providers wrapper at components/providers.tsx that wraps children in Auth0Provider using process.env.NEXT_PUBLIC_AUTH0_DOMAIN and process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID with authorizationParams.redirect_uri set to typeof window !== 'undefined' ? window.location.origin : ''. Import and use this provider in app/layout.tsx. Create a NavBar component at components/NavBar.tsx that shows Login/Logout buttons using useAuth0(). The login button calls loginWithRedirect(), the logout button calls logout({ logoutParams: { returnTo: window.location.origin } }). Show the user's avatar and name when authenticated.
Paste this in Bolt.new chat
1// components/providers.tsx2'use client';34import { Auth0Provider } from '@auth0/auth0-react';5import { useRouter } from 'next/navigation';67export function Providers({ children }: { children: React.ReactNode }) {8 const router = useRouter();910 const onRedirectCallback = (appState?: { returnTo?: string }) => {11 router.push(appState?.returnTo || '/');12 };1314 return (15 <Auth0Provider16 domain={process.env.NEXT_PUBLIC_AUTH0_DOMAIN!}17 clientId={process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID!}18 authorizationParams={{19 redirect_uri: typeof window !== 'undefined' ? window.location.origin : '',20 audience: process.env.NEXT_PUBLIC_AUTH0_AUDIENCE,21 }}22 onRedirectCallback={onRedirectCallback}23 >24 {children}25 </Auth0Provider>26 );27}2829// components/NavBar.tsx30'use client';3132import { useAuth0 } from '@auth0/auth0-react';3334export function NavBar() {35 const { isAuthenticated, isLoading, user, loginWithRedirect, logout } = useAuth0();3637 if (isLoading) return <nav className="h-16 bg-white border-b" />;3839 return (40 <nav className="h-16 bg-white border-b flex items-center justify-between px-6">41 <span className="font-semibold">My App</span>42 <div className="flex items-center gap-4">43 {isAuthenticated ? (44 <>45 {user?.picture && (46 <img src={user.picture} alt={user.name} className="w-8 h-8 rounded-full" />47 )}48 <span className="text-sm text-gray-700">{user?.name}</span>49 <button50 onClick={() => logout({ logoutParams: { returnTo: window.location.origin } })}51 className="text-sm text-red-600 hover:underline"52 >53 Log Out54 </button>55 </>56 ) : (57 <button58 onClick={() => loginWithRedirect()}59 className="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-blue-700"60 >61 Log In62 </button>63 )}64 </div>65 </nav>66 );67}Pro tip: Pass the audience parameter in authorizationParams when you want to get an access token that can be used to call a protected API. Without it, Auth0 issues an opaque token that cannot be validated by your API routes.
Expected result: The NavBar shows a Login button when not authenticated. Clicking it redirects to Auth0's login page. After successful login, the user's name and avatar appear in the NavBar. The entire flow works in the Bolt preview.
Create a Protected Profile Page
Create a Protected Profile Page
With authentication working, build a profile page that only authenticated users can access. In the Auth0 React SDK, use the withAuthenticationRequired higher-order component or check isAuthenticated in the component and redirect to login if false. The user object from useAuth0() contains the ID token claims: sub (unique user ID), name, email, picture, email_verified, and any custom claims you configure in Auth0 rules or actions. For getting data from a protected API route, use getAccessTokenSilently() to obtain an access token, then include it in the Authorization header of your fetch call. The access token is a JWT that your API route can validate to confirm the request is from an authenticated user. Add route protection using Next.js middleware for full-stack protection, or use the withAuthenticationRequired wrapper for client-side protection. For a smooth user experience, redirect to the login flow (rather than showing an error page) when an unauthenticated user tries to access a protected route.
Create a protected profile page at app/profile/page.tsx. Use the Auth0 useAuth0() hook. If isLoading is true, show a loading spinner. If isAuthenticated is false, call loginWithRedirect() automatically. When authenticated, show the user's avatar, name, email, and email_verified status in a profile card. Add a button 'Get My Data' that calls getAccessTokenSilently(), then fetches from /api/profile with the token in the Authorization header as Bearer {token}. Create the API route at app/api/profile/route.ts that extracts the user sub from the request and returns mock user-specific data.
Paste this in Bolt.new chat
1// app/profile/page.tsx2'use client';34import { useAuth0 } from '@auth0/auth0-react';5import { useEffect } from 'react';67export default function ProfilePage() {8 const { isAuthenticated, isLoading, user, loginWithRedirect, getAccessTokenSilently } = useAuth0();910 useEffect(() => {11 if (!isLoading && !isAuthenticated) {12 loginWithRedirect({ appState: { returnTo: '/profile' } });13 }14 }, [isAuthenticated, isLoading, loginWithRedirect]);1516 const fetchProtectedData = async () => {17 try {18 const token = await getAccessTokenSilently();19 const res = await fetch('/api/profile', {20 headers: { Authorization: `Bearer ${token}` },21 });22 const data = await res.json();23 console.log('Protected data:', data);24 } catch (err) {25 console.error('Error fetching protected data:', err);26 }27 };2829 if (isLoading) {30 return <div className="flex justify-center items-center h-64">Loading...</div>;31 }3233 if (!isAuthenticated || !user) return null;3435 return (36 <div className="max-w-lg mx-auto px-4 py-12">37 <div className="bg-white rounded-xl border shadow-sm p-8 text-center">38 {user.picture && (39 <img src={user.picture} alt={user.name} className="w-20 h-20 rounded-full mx-auto mb-4" />40 )}41 <h1 className="text-2xl font-bold mb-1">{user.name}</h1>42 <p className="text-gray-500 mb-2">{user.email}</p>43 <span className={`text-xs px-2 py-1 rounded-full ${44 user.email_verified ? 'bg-green-100 text-green-700' : 'bg-yellow-100 text-yellow-700'45 }`}>46 {user.email_verified ? 'Email verified' : 'Email not verified'}47 </span>48 <button49 onClick={fetchProtectedData}50 className="mt-6 block w-full bg-blue-600 text-white py-2 rounded-lg text-sm font-medium hover:bg-blue-700"51 >52 Get My Data53 </button>54 </div>55 </div>56 );57}Pro tip: getAccessTokenSilently() caches the access token and silently refreshes it before expiry using a hidden iframe. It may fail in some browsers with strict cookie policies if Auth0's domain is blocked — use loginWithRedirect({ prompt: 'none' }) as a fallback.
Expected result: The profile page automatically redirects unauthenticated users to Auth0 login. Authenticated users see their profile information. The 'Get My Data' button successfully calls the protected API route with the JWT token.
Protect API Routes with JWT Validation
Protect API Routes with JWT Validation
To protect Next.js API routes so only authenticated Auth0 users can call them, validate the JWT access token from the Authorization header. Auth0 uses RS256 signing with a public key accessible at your Auth0 domain's JWKS endpoint (https://your-domain.auth0.com/.well-known/jwks.json). Install the jose library for JWT verification: `npm install jose`. Create a middleware utility that fetches the public key from Auth0's JWKS endpoint and validates the token's signature, expiry, issuer, and audience. This utility runs server-side in your API routes. The validated payload contains the user's sub (unique ID) and any custom claims. For RBAC, configure Auth0 Actions to add a custom claim containing the user's roles to the access token (e.g., https://your-app.com/roles: ['admin', 'user']). Your API routes can then check this claim to enforce role-based access. Auth0 Actions are configured in Dashboard → Actions → Flows → Login. After deploying to Netlify, the JWT validation works identically since it only requires outbound HTTP calls to Auth0's JWKS endpoint.
Create a JWT validation utility at lib/auth0-verify.ts that uses the jose library to validate Auth0 access tokens. The function should accept a Request object, extract the Bearer token from the Authorization header, fetch Auth0's JWKS from https://{AUTH0_DOMAIN}/.well-known/jwks.json, and verify the token's signature, issuer, and audience. Return the decoded payload on success or throw an error. Update app/api/profile/route.ts to use this utility and return the user's sub and email from the token payload.
Paste this in Bolt.new chat
1// lib/auth0-verify.ts2import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';34interface Auth0Payload extends JWTPayload {5 sub: string;6 email?: string;7 name?: string;8 [key: string]: unknown;9}1011const JWKS = createRemoteJWKSet(12 new URL(`https://${process.env.NEXT_PUBLIC_AUTH0_DOMAIN}/.well-known/jwks.json`)13);1415export async function verifyAuth0Token(request: Request): Promise<Auth0Payload> {16 const authHeader = request.headers.get('Authorization');17 if (!authHeader?.startsWith('Bearer ')) {18 throw new Error('Missing or invalid Authorization header');19 }2021 const token = authHeader.slice(7);22 const domain = process.env.NEXT_PUBLIC_AUTH0_DOMAIN;23 const audience = process.env.NEXT_PUBLIC_AUTH0_AUDIENCE;2425 const { payload } = await jwtVerify(token, JWKS, {26 issuer: `https://${domain}/`,27 audience: audience || undefined,28 });2930 return payload as Auth0Payload;31}3233// app/api/profile/route.ts34import { NextResponse } from 'next/server';35import { verifyAuth0Token } from '@/lib/auth0-verify';3637export async function GET(request: Request) {38 try {39 const payload = await verifyAuth0Token(request);4041 return NextResponse.json({42 userId: payload.sub,43 email: payload.email,44 // Custom roles claim added via Auth0 Actions45 roles: payload['https://your-app.com/roles'] || [],46 });47 } catch (error) {48 return NextResponse.json(49 { error: 'Unauthorized' },50 { status: 401 }51 );52 }53}Pro tip: The createRemoteJWKSet call automatically caches the JWKS keys and refreshes them periodically. Do not call the JWKS endpoint on every request — the module-level constant handles caching efficiently.
Expected result: API routes protected with verifyAuth0Token return 401 for unauthenticated requests and the user's data for valid Auth0 tokens. The protection works in both the Bolt preview and on Netlify.
Common use cases
User Authentication for a SaaS Application
Add complete user authentication to a SaaS app: email/password login, Google OAuth, GitHub OAuth, and MFA support — all through Auth0 Universal Login. Users get secure, professionally designed login screens without any custom auth code, and you get session management, user profiles, and security best practices handled automatically.
Add Auth0 authentication to this Next.js app. Install @auth0/auth0-react. Create an Auth0Provider wrapper in app/providers.tsx using process.env.NEXT_PUBLIC_AUTH0_DOMAIN and process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID. Add a login button that calls loginWithRedirect() from useAuth0() and a logout button that calls logout(). Create a /profile page that shows the authenticated user's name, email, and avatar using the user object from useAuth0(). Redirect unauthenticated users trying to access /profile to the login flow.
Copy this prompt to try it in Bolt.new
Protected API Routes with JWT Validation
Secure Next.js API routes so only authenticated Auth0 users can access them. The frontend sends the Auth0 access token in the Authorization header; the API route validates the JWT before returning sensitive data. Essential for any application with user-specific data.
Create a protected API route pattern in Next.js with Auth0. Build a utility at lib/auth0-verify.ts that validates a Bearer JWT token from the Authorization header against the Auth0 JWKS endpoint at process.env.AUTH0_DOMAIN. Install jose for JWT verification. Create an example protected API route at app/api/profile/route.ts that uses this utility to verify the token and return the user's sub claim and custom claims. Show the correct fetch call from a React component including the getAccessTokenSilently() call to get the access token.
Copy this prompt to try it in Bolt.new
Role-Based Access Control Dashboard
Implement RBAC where different users see different parts of the application. Admin users see management panels; regular users see only their own data. Auth0 Roles and Permissions are included in the JWT access token after configuration, enabling the frontend and API routes to enforce access control.
Set up Auth0 RBAC in this Next.js app. Create an API route at app/api/admin/users/route.ts that validates the JWT access token and checks for an 'admin' role in the token's custom namespace claim. Add a frontend hook that reads the user's roles from the ID token and conditionally renders admin navigation links. Create a protected /admin page that redirects non-admin users to a 403 page.
Copy this prompt to try it in Bolt.new
Troubleshooting
Login redirect returns to the wrong URL or shows 'Callback URL mismatch' error
Cause: The Auth0 application's Allowed Callback URLs does not include the current URL (Bolt preview URL or localhost) that the user is redirecting back to.
Solution: In Auth0 Dashboard → Applications → your app → Settings → Allowed Callback URLs, add all possible URLs: your Bolt preview URL, http://localhost:3000, and your deployed Netlify URL. The Bolt preview URL changes with each session. Using window.location.origin for redirect_uri and adding wildcard-style URLs (Auth0 supports * wildcards in callback URLs for development) helps. For the most reliable development experience, deploy to Netlify and test auth there.
1// Use dynamic origin instead of hardcoded URL2authorizationParams={{3 redirect_uri: typeof window !== 'undefined' ? window.location.origin : '',4}}getAccessTokenSilently() throws 'Login required' even when the user is logged in
Cause: The Auth0 SDK cannot silently refresh the token in Bolt's WebContainer because the silent token refresh uses a hidden iframe, and the WebContainer origin is not in the Allowed Web Origins list.
Solution: Add your Bolt preview URL and localhost to Auth0 Dashboard → Applications → your app → Allowed Web Origins. Alternatively, catch the error and call loginWithRedirect({ prompt: 'none' }) as a non-interactive login, or deploy to Netlify where the origin is stable and always registered.
1try {2 const token = await getAccessTokenSilently();3} catch (error) {4 if (error instanceof Error && error.message.includes('Login required')) {5 await loginWithRedirect({ appState: { returnTo: window.location.pathname } });6 }7}JWT validation in API route fails with 'JWKSNoMatchingKey' error
Cause: The JWKS endpoint URL is incorrect, or the access token was issued for a different Auth0 domain than the one configured in environment variables.
Solution: Verify NEXT_PUBLIC_AUTH0_DOMAIN matches the domain shown in Auth0 Dashboard → your application (format: dev-xxxxx.us.auth0.com, without https://). The JWKS URL is built from this domain. Ensure the audience in your jwtVerify call matches the API identifier configured in Auth0 Dashboard → Applications → APIs.
1// Auth0 domain should not include 'https://'2// Correct: 'dev-xxxxx.us.auth0.com'3// Wrong: 'https://dev-xxxxx.us.auth0.com'4const JWKS = createRemoteJWKSet(5 new URL(`https://${process.env.NEXT_PUBLIC_AUTH0_DOMAIN}/.well-known/jwks.json`)6);Auth0 social login (Google, GitHub) fails in Bolt's preview with redirect errors
Cause: OAuth providers like Google require specific redirect URIs to be registered in their developer consoles. The Bolt preview URL may not be registered there.
Solution: For testing social login during development, deploy to Netlify first and register the stable Netlify URL in both Auth0 and the OAuth provider (e.g., Google Cloud Console → Credentials → OAuth 2.0 Client → Authorized redirect URIs). Auth0 handles the OAuth provider callback, but the initial redirect must come from a registered origin.
Best practices
- Register your deployed Netlify URL in Auth0's callback URLs immediately — it provides a stable URL for testing auth flows that does not change between sessions like the Bolt preview URL
- Use window.location.origin for the redirect_uri parameter rather than hardcoding URLs, so the same code works across all environments
- Set the audience parameter in Auth0Provider to get access tokens that can be validated by API routes, not just ID tokens
- Use Auth0 Actions (not deprecated Rules) to add custom claims like roles to access tokens for RBAC implementation
- Create a separate Auth0 application for development and production — never use the same credentials in both environments
- Implement logout with { logoutParams: { returnTo: window.location.origin } } to properly clear Auth0's session, not just the local state
- Cache the JWKS using createRemoteJWKSet at module level so the JWT validation does not fetch the JWKS endpoint on every request
Alternatives
Okta targets enterprise organizations with stronger workforce identity management, compliance features, and lifecycle management, while Auth0 (now part of Okta) is better suited for customer-facing applications with a friendlier developer experience.
Duo Security specializes in multi-factor authentication and zero-trust security for workforce users, while Auth0 provides a more complete customer identity solution including social login and user management.
LastPass is a password manager rather than an authentication platform, so it serves a completely different purpose — choose Auth0 for application authentication and LastPass for secure credential storage.
Firebase Authentication is tightly integrated with the Firebase ecosystem and simpler to set up for Google-centric apps, while Auth0 offers more enterprise features, better RBAC, and stronger compliance certifications.
Frequently asked questions
Does Auth0 work in Bolt.new during development without deploying?
Yes, with Universal Login. Auth0's redirect-based login flow works in Bolt's WebContainer preview because the OAuth redirect goes to Auth0's domain (auth.yourtenantname.auth0.com), which is externally accessible. Add your Bolt preview URL to Auth0's Allowed Callback URLs and the flow completes correctly. Silent token refresh (getAccessTokenSilently) may be less reliable in the preview — this is the main reason to also test on a deployed URL.
What is Universal Login and why is it recommended for Bolt.new?
Universal Login is Auth0's hosted login page at your Auth0 domain. When a user clicks login, they are redirected to Auth0's servers to authenticate, then redirected back to your app. This works in Bolt's WebContainer because the authentication happens on Auth0's domain, not inside the WebContainer. The alternative — embedded login using a popup or modal — has more CORS and iframe restrictions in browser environments.
How do I add social login (Google, GitHub) with Auth0 in Bolt.new?
Enable social connections in Auth0 Dashboard → Authentication → Social. Auth0 provides development-level credentials for Google and GitHub that work without registering your own OAuth apps in their developer consoles. For production, you should configure your own OAuth credentials in Auth0's social connection settings — this removes Auth0's branding from the consent screen and improves reliability.
What is the difference between Auth0 ID tokens and access tokens?
ID tokens contain user identity information (name, email, picture) and are intended for your frontend application to display user profile data. Access tokens are credentials that authorize API calls and should be sent in the Authorization header to your protected API routes. Always validate access tokens in API routes using the JWKS endpoint, never trust token data without validation.
How many users can I have on Auth0's free plan?
Auth0's free plan (Essentials) supports 7,500 monthly active users (MAU) — a user counts toward MAU if they log in at least once in a calendar month. The free plan also includes social login connections, up to 3 Actions, and basic attack protection. For RBAC, enterprise connections, or more advanced features, the Professional plan starts at $240/month.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation