Skip to main content

Express.js

This example shows how to integrate CentralAuth with an Express.js server using the CentralAuth NPM library. We'll create a simple JavaScript web application with authentication, demonstrating login, callback handling, user information retrieval and logout functionality.

note

Note that this example will also work for any other Node.js framework that uses Express-style middleware.

Step 1: Create a new Express.js project

First, create a new directory and initialize a Node.js project:

mkdir my-express-auth-app
cd my-express-auth-app
npm init -y

Step 2: Install dependencies

Install Express.js and the CentralAuth library along with other necessary dependencies:

npm install --save express centralauth dotenv

Step 3: Set up environment variables

Create a .env file in the root of your project:

AUTH_ORGANIZATION_ID=your_organization_id
AUTH_SECRET=your_secret
AUTH_BASE_URL=centralauth_base_url
PORT=3000

Replace the example values with:

  • AUTH_ORGANIZATION_ID and AUTH_SECRET: Get these from your CentralAuth integration page
  • AUTH_BASE_URL: Use https://centralauth.com or your custom domain
  • PORT: The port your Express.js server will run on (default is 3000)

Step 4: Create the main server file

Create a file server.js:

import { CentralAuthHTTPClass } from 'centralauth/src/server.js';
import dotenv from 'dotenv';
import express from 'express';

dotenv.config();

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

const getCentralAuthInstance = () => {
// Initialize CentralAuth
// Make sure to get a new instance for each request to avoid state issues!
return new CentralAuthHTTPClass({
clientId: process.env.AUTH_ORGANIZATION_ID,
secret: process.env.AUTH_SECRET,
authBaseUrl: process.env.AUTH_BASE_URL,
callbackUrl: `http://localhost:${PORT}/auth/callback`
});
}

// Middleware to parse JSON
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Routes
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>CentralAuth Express Example</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
text-align: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
}
.container {
background: rgba(255, 255, 255, 0.95);
padding: 40px;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
backdrop-filter: blur(10px);
}
h1 {
color: #4a90e2;
margin-bottom: 10px;
font-weight: 300;
font-size: 2.5em;
}
#auth-section {
margin: 30px 0;
}
.btn, button.btn {
display: inline-block;
padding: 12px 24px;
background: #007bff;
color: white;
text-decoration: none;
border-radius: 8px;
margin: 10px 8px;
font-weight: 600;
font-size: 16px;
border: none;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
font-family: inherit;
}
.btn:hover, button.btn:hover {
background: #0056b3;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.btn-success, button.btn-success {
background: #28a745;
}
.btn-success:hover, button.btn-success:hover {
background: #1e7e34;
}
.btn-danger, button.btn-danger {
background: #dc3545;
}
.btn-danger:hover, button.btn-danger:hover {
background: #c82333;
}
</style>
</head>
<body>
<div class="container">
<h1>CentralAuth Express.js Example</h1>
<p>Welcome to the CentralAuth integration example using Express.js!</p>

<div id="auth-section">
<a href="/auth/login" class="btn">Login with CentralAuth</a>
<a href="/profile" class="btn btn-success">View Profile</a>
<a href="/auth/logout" class="btn btn-danger">Logout</a>
</div>
</div>
</body>
</html>
`);
});

// Authentication routes
app.get('/auth/login', async (req, res) => {
try {
const authClient = getCentralAuthInstance();
await authClient.loginHTTP(req, res, { returnTo: `http://localhost:${PORT}/profile` });
} catch (error) {
console.error('Login error:', error);
res.status(500).send('Authentication failed');
}
});

app.get('/auth/callback', async (req, res) => {
try {
const authClient = getCentralAuthInstance();
await authClient.callbackHTTP(req, res);
} catch (error) {
console.error('Callback error:', error);
res.status(500).send('Authentication callback failed');
}
});

app.get('/auth/user', async (req, res) => {
try {
const authClient = getCentralAuthInstance();
await authClient.userHTTP(req, res);
} catch (error) {
console.error('User info error:', error);
res.status(500).json({ error: 'Failed to get user information' });
}
});

app.get('/auth/logout', async (req, res) => {
try {
const authClient = getCentralAuthInstance();
// Handle logout with CentralAuth
await authClient.logoutHTTP(req, res, { returnTo: `http://localhost:${PORT}` });
} catch (error) {
console.error('Logout error:', error);
res.redirect('/?error=logout_failed');
}
});

// Profile page
app.get('/profile', async (req, res) => {
let user = null;
try {
const authClient = getCentralAuthInstance();
user = await authClient.getUserDataHTTP(req);
} catch (error) {
console.log('Could not fetch fresh user data');
res.redirect('/?error=not_logged_in');
}

res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Profile - CentralAuth Express Example</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
text-align: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
}
.container {
background: rgba(255, 255, 255, 0.95);
padding: 40px;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
backdrop-filter: blur(10px);
}
h1 {
color: #4a90e2;
margin-bottom: 20px;
font-weight: 300;
font-size: 2.2em;
}
.btn, button.btn {
display: inline-block;
padding: 12px 24px;
background: #007bff;
color: white;
text-decoration: none;
border-radius: 8px;
margin: 10px 8px;
font-weight: 600;
font-size: 16px;
border: none;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
font-family: inherit;
}
.btn:hover, button.btn:hover {
background: #0056b3;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.btn-success, button.btn-success {
background: #28a745;
}
.btn-success:hover, button.btn-success:hover {
background: #1e7e34;
}
.btn-danger, button.btn-danger {
background: #dc3545;
}
.btn-danger:hover, button.btn-danger:hover {
background: #c82333;
}
.user-info {
text-align: center;
background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%);
border: 1px solid #c3e6cb;
color: #155724;
padding: 25px;
border-radius: 15px;
margin: 25px 0;
box-shadow: 0 4px 15px rgba(40, 167, 69, 0.1);
}
.user-info h3 {
margin-bottom: 15px;
color: #0f5132;
font-size: 1.4em;
}
.success {
background: linear-gradient(135deg, #d1ecf1 0%, #b8daff 100%);
border: 1px solid #b8daff;
color: #0c5460;
padding: 15px;
border-radius: 10px;
margin: 15px 0;
font-weight: 500;
box-shadow: 0 4px 15px rgba(13, 110, 253, 0.1);
}
</style>
</head>
<body>
<div class="container">
<h1>User Profile</h1>

${req.query.success ? '<div class="success">Successfully logged in!</div>' : ''}

${user ? `
<div class="user-info">
<h3>Welcome!</h3>
<img src="${user.gravatar}" alt="User Avatar" style="border-radius: 50%; width: 80px; height: 80px; margin-vertical: 8px;">
<p><strong>Email:</strong> ${user.email}</p>
</div>
` : `
<p>You are not logged in.</p>
`}

<div>
<a href="/" class="btn">Back to Home</a>
<button onclick="fetchUserInfo()" class="btn btn-success">Refresh User Info</button>
<a href="/auth/logout" class="btn btn-danger">Logout</a>
</div>
</div>

<script>
async function fetchUserInfo() {
try {
const response = await fetch('/auth/user');
if (response.ok) {
const userData = await response.json();
alert('User info: ' + JSON.stringify(userData, null, 2));
} else {
alert('Failed to fetch user info. Please log in.');
}
} catch (error) {
alert('Error fetching user info: ' + error.message);
}
}
</script>
</body>
</html>
`);
});

// Start server
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
console.log('Environment variables loaded:');
console.log('- AUTH_ORGANIZATION_ID:', process.env.AUTH_ORGANIZATION_ID ? '✓' : '✗');
console.log('- AUTH_SECRET:', process.env.AUTH_SECRET ? '✓' : '✗');
console.log('- AUTH_BASE_URL:', process.env.AUTH_BASE_URL || 'Not set');
});

export default app;

Step 5: Run the application

Start the Express.js application:

node server.js

Navigate to http://localhost:3000 to see your application running.