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

  1. Navigate to GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.

  2. Set the Authorization callback URL to:

    
    ${PROTOCOL}://${HOST}:${PORT}/auth/github/callback
    

    For local development, this is typically http://localhost:3001/auth/github/callback.

  3. 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/github and /auth/github/callback routes.
  • server/auth/auth_utils.js: Provides the verifyUser callback that Passport uses to validate GitHub profiles and the session_user helper to retrieve the current user from the session store.
  • server/server.js: Conditionally imports and mounts the authRouter when 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=true in your environment to trigger the conditional loading of authRouter in server/server.js.
  • Configure credentials using GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, and SESSION_SECRET environment variables.
  • Implement the flow via server/auth/auth_router.js, which configures the Passport GitHub strategy, initializes express-session, and exposes /auth/github and /auth/github/callback endpoints.
  • Validate users through the verifyUser callback in server/auth/auth_utils.js, which accepts GitHub profiles and assigns roles.
  • Protect routes using the checkAuthenticated middleware 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →