Skip to main content

Documentation Index

Fetch the complete documentation index at: https://auth0.com/llms.txt

Use this file to discover all available pages before exploring further.

This Quickstart is currently in Beta. We’d love to hear your feedback!
Prerequisites: Before you begin, ensure you have the following installed:

Get Started

This guide demonstrates how to integrate Auth0, add authentication, and display user profile information in an Express.js web application using the @auth0/auth0-express SDK.
1

Create a new project

Create a new directory for your Express application and initialize a Node.js project.Update your package.json to use ES modules and add start scripts:
{
  "name": "auth0-express-app",
  "version": "1.0.0",
  "type": "module",
  "main": "server.js",
  "scripts": {
    "start": "node server.js",
    "dev": "node --watch server.js"
  }
}
2

Install the SDK

Install @auth0/auth0-express along with express and dotenv:
npm install @auth0/auth0-express@beta express dotenv
3

Configure Auth0

You need to create a new application on your Auth0 tenant and configure your environment variables.
Once your app is created, add these values to your .env file:Generate a secure session secret:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Copy the output and use it as the AUTH0_SESSION_SECRET value.
On macOS or Linux you can also run openssl rand -hex 32. The Node command works on every platform, since Node is already a prerequisite.
4

Configure the middleware

Add the createAuth0() middleware to your Express application. The SDK automatically mounts /auth/login, /auth/logout, /auth/callback, and /auth/backchannel-logout routes.
server.js
import 'dotenv/config';
import express from 'express';
import { createAuth0 } from '@auth0/auth0-express';

const app = express();
const port = process.env.PORT || 3000;

app.use(createAuth0());

app.get('/', async (req, res) => {
  const session = await req.auth0.client.getSession();
  res.send(session ? 'Logged in' : 'Logged out');
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
What this does:
  • createAuth0() reads credentials from environment variables (AUTH0_DOMAIN, AUTH0_CLIENT_ID, etc.) automatically
  • Mounts four auth routes under /auth/
  • Attaches req.auth0.client to every request for session and token access
5

Add login, logout, and a protected profile route

Protect routes using the requiresAuth middleware from the SDK, and display user profile data via getUser().
server.js
import 'dotenv/config';
import express from 'express';
import { createAuth0, requiresAuth } from '@auth0/auth0-express';

const app = express();
const port = process.env.PORT || 3000;

app.use(createAuth0());

// Public home route
app.get('/', async (req, res) => {
  const session = await req.auth0.client.getSession();
  const isAuthenticated = !!session;

  res.send(`
    <html>
      <head>
        <title>Auth0 Express (Beta) Quickstart</title>
        <style>
          body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto; }
          a { color: #0066cc; text-decoration: none; margin-right: 1rem; }
          .status { padding: 1rem; border-radius: 4px; margin: 1rem 0; }
          .logged-in { background: #d4edda; color: #155724; }
          .logged-out { background: #f8d7da; color: #721c24; }
        </style>
      </head>
      <body>
        <h1>Auth0 Express (Beta) Quickstart</h1>
        <div class="status ${isAuthenticated ? 'logged-in' : 'logged-out'}">
          ${isAuthenticated ? '✓ You are logged in' : '✗ You are logged out'}
        </div>
        <nav>
          ${isAuthenticated
            ? '<a href="/profile">Profile</a> | <a href="/auth/logout">Logout</a>'
            : '<a href="/auth/login">Login</a>'}
        </nav>
      </body>
    </html>
  `);
});

// Protected profile route — requiresAuth redirects unauthenticated users to /auth/login
app.get('/profile', requiresAuth(), async (req, res) => {
  const user = await req.auth0.client.getUser();

  res.send(`
    <html>
      <head>
        <title>Profile</title>
        <style>
          body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto; }
          pre { background: #f4f4f4; padding: 1rem; border-radius: 4px; overflow-x: auto; }
          img { border-radius: 50%; }
        </style>
      </head>
      <body>
        <h1>User Profile</h1>
        ${user.picture ? `<img src="${user.picture}" alt="Profile" width="80" />` : ''}
        <h2>${user.name || user.nickname || 'User'}</h2>
        <p><strong>Email:</strong> ${user.email || 'N/A'}</p>
        <h3>Full Profile</h3>
        <pre>${JSON.stringify(user, null, 2)}</pre>
        <a href="/">← Back</a> | <a href="/auth/logout">Logout</a>
      </body>
    </html>
  `);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
Key points:
  • requiresAuth() from @auth0/auth0-express protects routes — unauthenticated users are redirected to /auth/login
  • req.auth0.client.getUser() returns the authenticated user’s profile
  • Login link points to /auth/login, logout to /auth/logout — both are automatically mounted
6

Run your application

Start the development server:
npm run dev
Open your browser to http://localhost:3000.
CheckpointYou should now have a fully functional Auth0 login flow. When you:
  1. Click Login — you’re redirected to Auth0’s Universal Login page
  2. Complete authentication — you’re redirected back to your app at /auth/callback
  3. Visit /profile — you see your user information
  4. Click Logout — your session is cleared and you’re logged out of Auth0

Advanced Usage

Configure the SDK with an audience to request an access token for your API, then retrieve it with getAccessToken().Add your API audience to .env:
.env
AUTH0_AUDIENCE=https://your-api.example.com
Retrieve the token in a protected route:
server.js
app.get('/api-data', requiresAuth(), async (req, res) => {
  const { accessToken } = await req.auth0.client.getAccessToken();

  const response = await fetch('https://your-api.example.com/data', {
    headers: { Authorization: `Bearer ${accessToken}` },
  });

  res.json(await response.json());
});
The SDK handles token refresh automatically when the access token expires.
Redirect users back to a specific page after login using the returnTo parameter:
server.js
app.get('/dashboard', async (req, res) => {
  const session = await req.auth0.client.getSession();
  if (!session) {
    return res.redirect('/auth/login?returnTo=/dashboard');
  }
  res.send('Welcome to your dashboard!');
});
Build your own authorization logic on top of the session:
server.js
async function requireAdmin(req, res, next) {
  const user = await req.auth0.client.getUser();
  if (!user) return res.redirect('/auth/login');
  if (!user['https://myapp.com/roles']?.includes('admin')) {
    return res.status(403).send('Forbidden');
  }
  next();
}

app.get('/admin', requireAdmin, (req, res) => {
  res.send('Admin panel');
});
The https://myapp.com/roles claim is not present by default — add it to the ID token with an Action and use a namespaced claim name.

Troubleshooting

Cause: createAuth0() middleware was not registered before your route handler.Fix: Ensure app.use(createAuth0()) appears before any route that accesses req.auth0:
// ✅ Correct
app.use(createAuth0());
app.get('/profile', requiresAuth(), handler);

// ❌ Wrong
app.get('/profile', requiresAuth(), handler);
app.use(createAuth0());
Cause: The callback URL in your Auth0 Application Settings does not match http://localhost:3000/auth/callback.Fix:
  1. Go to Auth0 DashboardApplications > Applications → your app → Application Settings
  2. Add http://localhost:3000/auth/callback to Allowed Callback URLs
  3. Add http://localhost:3000 to Allowed Logout URLs
  4. Click Save Changes
Note: the @auth0/auth0-express SDK uses /auth/callback (not /callback as in express-openid-connect).
Cause: dotenv/config is not imported, or the .env file is missing required values.Fix:
  1. Ensure import 'dotenv/config' (or require('dotenv').config()) is at the top of your entry file
  2. Verify your .env contains all five required variables: AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET, APP_BASE_URL, AUTH0_SESSION_SECRET
  3. Debug missing values:
console.log({
  domain: !!process.env.AUTH0_DOMAIN,
  clientId: !!process.env.AUTH0_CLIENT_ID,
  clientSecret: !!process.env.AUTH0_CLIENT_SECRET,
  appBaseUrl: !!process.env.APP_BASE_URL,
  sessionSecret: !!process.env.AUTH0_SESSION_SECRET,
});
Cause: Session cookie is not being set correctly, or the callback URL is accessed directly.Fix:
  1. Ensure APP_BASE_URL matches the URL you access in your browser (e.g., http://localhost:3000)
  2. Clear your browser cookies and try again
  3. In production, ensure you are using HTTPS

Next Steps


Resources