auth0-express
Use when adding authentication (login, logout, protected routes) to Express.js web applications - integrates express-openid-connect for session-based auth.
What this skill does
# Auth0 Express Integration
Add authentication to Express.js web applications using express-openid-connect.
---
## Prerequisites
- Express.js application
- Auth0 account and application configured
- If you don't have Auth0 set up yet, use the `auth0-quickstart` skill first
## When NOT to Use
- **Single Page Applications** - Use `auth0-react`, `auth0-vue`, or `auth0-angular` for client-side auth
- **Next.js applications** - Use `auth0-nextjs` skill which handles both client and server
- **Mobile applications** - Use `auth0-react-native` for React Native/Expo
- **Stateless APIs** - Use JWT validation middleware instead of session-based auth
- **Microservices** - Use JWT validation for service-to-service auth
---
## Quick Start Workflow
### 1. Install SDK
```bash
npm install express-openid-connect dotenv
```
### 2. Configure Environment
**For automated setup with Auth0 CLI**, see [Setup Guide](references/setup.md) for complete scripts.
**For manual setup:**
Create `.env`:
```bash
SECRET=<openssl-rand-hex-32>
BASE_URL=http://localhost:3000
CLIENT_ID=your-client-id
CLIENT_SECRET=your-client-secret
ISSUER_BASE_URL=https://your-tenant.auth0.com
AUDIENCE=https://your-api-identifier # only required if calling external APIs (Step 3a)
```
Generate secret: `openssl rand -hex 32`
### 3. Configure Auth Middleware
Update your Express app (`app.js` or `index.js`):
```javascript
require('dotenv').config();
const express = require('express');
const { auth, requiresAuth } = require('express-openid-connect');
const app = express();
// Configure Auth0 middleware
app.use(auth({
authRequired: false, // Don't require auth for all routes
auth0Logout: true, // Enable logout endpoint
secret: process.env.SECRET,
baseURL: process.env.BASE_URL,
clientID: process.env.CLIENT_ID,
issuerBaseURL: process.env.ISSUER_BASE_URL,
clientSecret: process.env.CLIENT_SECRET
}));
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
```
> **Calling external APIs?** If you need an access token for a downstream API, you **must** add `authorizationParams` — see Step 3a below.
This automatically creates:
- `/login` - Login endpoint
- `/logout` - Logout endpoint
- `/callback` - OAuth callback
### 3a. Configure Middleware for API Access (when calling external APIs)
When you need an access token for an external API, `audience` **must** go inside `authorizationParams` — putting it at the top level is silently ignored and no access token is issued.
```javascript
// SDK auto-loads SECRET, BASE_URL, CLIENT_ID, ISSUER_BASE_URL, CLIENT_SECRET from env vars
app.use(auth({
authRequired: false,
auth0Logout: true,
authorizationParams: { // ← required for access tokens
response_type: 'code', // ← required: authorization code flow
audience: process.env.AUDIENCE, // ← API identifier (never top-level)
scope: 'openid profile email'
}
}));
```
Then access the token in your route:
```javascript
app.get('/api-call', requiresAuth(), async (req, res) => {
const { access_token } = req.oidc.accessToken; // object, not a string
const response = await fetch('https://your-api.com/data', {
headers: { Authorization: `Bearer ${access_token}` }
});
res.json(await response.json());
});
```
### 4. Add Routes
```javascript
// Public route
app.get('/', (req, res) => {
res.send(req.oidc.isAuthenticated() ? 'Logged in' : 'Logged out');
});
// Protected route
app.get('/profile', requiresAuth(), (req, res) => {
res.send(`
<h1>Profile</h1>
<p>Name: ${req.oidc.user.name}</p>
<p>Email: ${req.oidc.user.email}</p>
<pre>${JSON.stringify(req.oidc.user, null, 2)}</pre>
<a href="/logout">Logout</a>
`);
});
// Login/logout links
app.get('/', (req, res) => {
res.send(`
${req.oidc.isAuthenticated() ? `
<p>Welcome, ${req.oidc.user.name}!</p>
<a href="/profile">Profile</a>
<a href="/logout">Logout</a>
` : `
<a href="/login">Login</a>
`}
`);
});
```
### 5. Test Authentication
Start your server:
```bash
node app.js
```
Visit `http://localhost:3000` and test the login flow.
---
## Detailed Documentation
- **[Setup Guide](references/setup.md)** - Automated setup scripts, environment configuration, Auth0 CLI usage
- **[Integration Guide](references/integration.md)** - Protected routes, sessions, API integration, error handling
- **[API Reference](references/api.md)** - Complete middleware API, configuration options, request properties
---
## Common Mistakes
| Mistake | Fix |
|---------|-----|
| Forgot to add callback URL in Auth0 Dashboard | Add `/callback` path to Allowed Callback URLs (e.g., `http://localhost:3000/callback`) |
| Missing or weak SECRET | Generate secure secret with `openssl rand -hex 32` and store in .env as `SECRET` |
| Setting authRequired: true globally | Set to false and use `requiresAuth()` middleware on specific routes |
| App created as SPA type in Auth0 | Must be Regular Web Application type for server-side auth |
| Session secret exposed in code | Always use environment variables, never hardcode secrets |
| Wrong baseURL for production | Update BASE_URL to match your production domain |
| Not handling logout returnTo | Add your domain to Allowed Logout URLs in Auth0 Dashboard |
| `audience` as a top-level config key | Move `audience` inside `authorizationParams` with `response_type: 'code'` and `scope` — top-level `audience` is silently ignored, no access token is issued |
| `req.oidc.accessToken` used as a string | It is an object — destructure with `const { access_token } = req.oidc.accessToken` |
---
## Related Skills
- `auth0-quickstart` - Basic Auth0 setup
- `auth0-migration` - Migrate from another auth provider
- `auth0-mfa` - Add Multi-Factor Authentication
- `auth0-cli` - Manage Auth0 resources from the terminal
---
## Quick Reference
**Middleware Options:**
- `authRequired` - Require auth for all routes (default: false)
- `auth0Logout` - Enable /logout endpoint (default: false)
- `secret` - Session secret (required)
- `baseURL` - Application URL (required)
- `clientID` - Auth0 client ID (required)
- `issuerBaseURL` - Auth0 tenant URL (required)
**Request Properties:**
- `req.oidc.isAuthenticated()` - Check if user is logged in
- `req.oidc.user` - User profile object
- `req.oidc.accessToken` - Access token object (`{ access_token, token_type, expires_in }`); `expires_in` is seconds remaining. Destructure with `const { access_token } = req.oidc.accessToken`. Also exposes `isExpired()` and `refresh()` methods. Only populated when `authorizationParams` with `audience` + `response_type: 'code'` is configured
- `req.oidc.idToken` - ID token
- `req.oidc.refreshToken` - Refresh token
**Common Use Cases:**
- Protected routes → Use `requiresAuth()` middleware (see Step 4)
- Check auth status → `req.oidc.isAuthenticated()`
- Get user info → `req.oidc.user`
- Call APIs → [Integration Guide](references/integration.md#calling-apis)
---
## References
- [Express OpenID Connect Documentation](https://auth0.com/docs/libraries/express-openid-connect)
- [Auth0 Express Quickstart](https://auth0.com/docs/quickstart/webapp/express)
- [SDK GitHub Repository](https://github.com/auth0/express-openid-connect)
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.