How to Set Up GitHub OAuth Authentication with Express and Passport in astro-big-doc
The astro-big-doc repository provides a complete GitHub OAuth implementation using Express, passport-github, and express-session that activates when ENABLE_AUTH is set to "true", automatically protecting routes via the authRouter and checkAuthenticated middleware.
The astro-big-doc project ships with a production-ready authentication system that integrates GitHub OAuth with an Express server using Passport.js. This guide explains how to configure and enable the GitHub OAuth flow using the built-in authentication modules, environment variables, and middleware found in server/server.js and the server/auth/ directory.
Prerequisites and Environment Configuration
Before enabling OAuth, you must configure your GitHub App credentials and environment variables. The system reads from process.env as defined in .env.example.
Create a GitHub OAuth App
-
Navigate to GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.
-
Set the Authorization callback URL to:
${PROTOCOL}://${HOST}:${PORT}/auth/github/callbackFor local development, this is typically
http://localhost:3001/auth/github/callback. -
Copy the Client ID and Client Secret for the next step.
Configure Environment Variables
Create or edit your .env file in the project root:
ENABLE_AUTH=true
GITHUB_CLIENT_ID=your_client_id_here
GITHUB_CLIENT_SECRET=your_client_secret_here
SESSION_SECRET=your_random_session_secret
PROTOCOL=http
HOST=0.0.0.0
PORT=3001
Setting ENABLE_AUTH to "true" triggers the conditional loading of the authentication router in server/server.js.
Authentication Architecture Overview
The OAuth implementation spans three main files in the server/auth/ directory:
server/auth/auth_router.js: Configures the Passport GitHub strategy, initializes sessions, and defines the/auth/githuband/auth/github/callbackroutes.server/auth/auth_utils.js: Provides theverifyUsercallback that Passport uses to validate GitHub profiles and thesession_userhelper to retrieve the current user from the session store.server/server.js: Conditionally imports and mounts theauthRouterwhen authentication is enabled.
Step-by-Step Implementation
Initialize the Authentication Router
In server/server.js, the authentication system is loaded dynamically to avoid overhead when disabled:
import * as dotenv from 'dotenv';
dotenv.config();
// ... other middleware ...
if (process.env.ENABLE_AUTH === "true") {
const { authRouter } = await import('./auth/auth_router.js');
app.use(authRouter);
}
This pattern ensures that Passport and session middleware are only instantiated when ENABLE_AUTH is explicitly enabled.
Configure Passport GitHub Strategy
The auth_router.js file initializes the GitHub OAuth strategy using credentials from environment variables:
import passport from 'passport';
import { Strategy as GitHubStrategy } from 'passport-github';
import { verifyUser } from './auth_utils.js';
const callbackURL = `${process.env.PROTOCOL}://${process.env.HOST}:${process.env.PORT}/auth/github/callback`;
passport.use(new GitHubStrategy(
{
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL: callbackURL,
},
verifyUser
));
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));
The verifyUser function (defined in auth_utils.js) accepts any GitHub profile for this demo implementation, assigning a default role and groups.
Set Up Session Handling
The router configures an in-memory session store using express-session:
import session from 'express-session';
const sessionHandler = session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
store: new session.MemoryStore(),
});
authRouter.use(sessionHandler);
authRouter.use(passport.initialize());
authRouter.use(passport.session());
After successful authentication, the system stores a mapping between the session ID and the GitHub user ID in process.env, enabling retrieval via the session_user helper in auth_utils.js.
Define Authentication Routes
Two routes handle the OAuth flow:
// Redirect to GitHub consent screen
authRouter.get('/auth/github', passport.authenticate('github'));
// Handle OAuth callback
authRouter.get(
'/auth/github/callback',
passport.authenticate('github', { failureRedirect: '/access' }),
(req, res) => {
// Redirect to originally requested page
res.redirect(req.session.returnTo || '/');
}
);
Protect Routes with Middleware
The checkAuthenticated middleware guards protected routes by verifying the session:
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
req.session.returnTo = req.originalUrl;
res.redirect('/auth/github');
}
Apply this middleware to any Express routes requiring authentication:
app.get('/admin', checkAuthenticated, (req, res) => {
res.render('admin');
});
Summary
- Enable authentication by setting
ENABLE_AUTH=truein your environment to trigger the conditional loading ofauthRouterinserver/server.js. - Configure credentials using
GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET, andSESSION_SECRETenvironment variables. - Implement the flow via
server/auth/auth_router.js, which configures the Passport GitHub strategy, initializesexpress-session, and exposes/auth/githuband/auth/github/callbackendpoints. - Validate users through the
verifyUsercallback inserver/auth/auth_utils.js, which accepts GitHub profiles and assigns roles. - Protect routes using the
checkAuthenticatedmiddleware to redirect unauthenticated users to the GitHub login flow.
Frequently Asked Questions
What environment variables are required to enable GitHub OAuth in astro-big-doc?
You must set ENABLE_AUTH to "true" to activate the authentication system. Additionally, provide GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET from your GitHub OAuth App, plus a SESSION_SECRET for signing cookies. Optional variables include PROTOCOL, HOST, and PORT to construct the callback URL.
How does the server handle user sessions after successful GitHub authentication?
After GitHub validates the credentials, the verifyUser function in auth_utils.js processes the profile. The auth_router.js then stores a mapping between the session ID and GitHub user ID in process.env, allowing the session_user helper to retrieve the current user on subsequent requests. Sessions use express-session with an in-memory store by default.
Can I restrict which GitHub users are allowed to access the application?
Yes. Modify the verifyUser function in server/auth/auth_utils.js to implement your own authorization logic. Instead of accepting every profile, check profile.username or profile.id against an allowlist, or query an external database. Return cb(null, profile) only for authorized users, or cb(null, false) to reject access.
What happens if GitHub OAuth authentication fails?
If authentication fails (user denies access or an error occurs), Passport redirects to the failureRedirect path specified in the callback route handler, which defaults to /access in the provided configuration. You should create an error page at this route or modify the failureRedirect value in auth_router.js to point to a custom error handler.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →