Discord Login Flow
Express.js serving static HTML files incorporating a Discord OAuth login flow to a protected dashboard.
Discord Login Template
An Express template that adds a "Login with Discord" flow (OAuth2) and a protected dashboard page, using plain HTML/CSS/JS on the frontend โ no templating engine required.
How it works
- User clicks Login with Discord on
index.html, which sends them to/auth/discord. - That route redirects them to Discord's consent screen.
- After approving, Discord redirects back to
/auth/discord/callbackwith a code. - The server exchanges that code for an access token, fetches the user's Discord profile, and stores it in a server-side session.
- The user is redirected to
/dashboard, which calls/api/userto fetch and display their info. /auth/logoutdestroys the session and sends them back to the login page.
/dashboard is protected โ if there's no active session, requesting it redirects straight back to /. Static files are served without their .html extension (express.static is configured with extensions: ['html']), so /dashboard maps to public/dashboard.html and / maps to public/index.html.
Getting Started
Create a Discord application
- Go to the Discord Developer Portal and click New Application.
- Under OAuth2 โ General, copy your Client ID and Client Secret.
- Under OAuth2 โ Redirects, add:(update the port/domain if you change it later)
http://localhost:3000/auth/discord/callback
3. Set up your environment variables
Copy the example env file:
cp example.env .env
Then fill in .env:
PORT=3000
DISCORD_CLIENT_ID=your_client_id
DISCORD_CLIENT_SECRET=your_client_secret
DISCORD_REDIRECT_URI=http://localhost:3000/auth/discord/callback
SESSION_SECRET=any_long_random_string
Project Structure
.
โโโ index.js # Express server, session setup, OAuth routes
โโโ example.env # Rename to .env in production
โโโ package.json
โโโ example.env
โโโ public/
โโโ index.html # Login page
โโโ dashboard.html # Protected dashboard (client-side rendered)
โโโ css/
โโโ styles.css
Customizing
- Scopes โ the login route requests
identify email. Add more scopes (e.g.guilds) in thescopeparameter inside the/auth/discordroute inindex.js, and update the callback to fetch/store any extra data you need. - Session storage โ sessions currently live in memory, which resets on server restart and won't scale across multiple server instances. For production, swap in a persistent session store (e.g.
connect-redisorconnect-mongo). - Dashboard content โ
dashboard.htmlcurrently shows username, tag, user ID, and email. Extend the/api/userroute inindex.jsto return more data, and update the script indashboard.htmlto display it. - Styling โ all styles are in
public/css/styles.css.
Notes
- Requires Node 18+ (uses the built-in global
fetch). - Never commit your real
.envfile โ onlyexample.envshould be checked into version control.