Google and GitHub Login via Passport OAuth Strategies
OAuth & Social Login
Add "Sign in with Google" or "Sign in with GitHub" to a Koa app using passport OAuth strategies, callback routes, and session-backed profile storage.
What you'll learn
- Register a Passport OAuth strategy with client credentials
- Implement the redirect and callback routes for the OAuth flow
- Upsert the provider profile into your database and store the user in session
OAuth 2.0 lets users authenticate via a trusted third party (Google, GitHub, etc.) without giving your app their password. Passport strategies handle the redirect, token exchange, and profile fetch; you only need to store the result.
Installation
npm install passport-google-oauth20 passport-github2 Ensure koa-passport and koa-session are already configured as shown in the
previous lesson.
Google Strategy
import { Strategy as GoogleStrategy } from "passport-google-oauth20";
import { upsertUser } from "./db.js";
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "https://yourdomain.com/auth/google/callback",
},
async (accessToken, refreshToken, profile, done) => {
try {
// Store only what you need; never store the raw accessToken long-term.
const user = await upsertUser({
provider: "google",
providerId: profile.id,
email: profile.emails?.[0]?.value,
displayName: profile.displayName,
});
done(null, user);
} catch (err) {
done(err);
}
}
)
); GitHub Strategy
import { Strategy as GitHubStrategy } from "passport-github2";
passport.use(
new GitHubStrategy(
{
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL: "https://yourdomain.com/auth/github/callback",
},
async (accessToken, refreshToken, profile, done) => {
try {
const user = await upsertUser({
provider: "github",
providerId: String(profile.id),
email: profile.emails?.[0]?.value,
displayName: profile.displayName ?? profile.username,
});
done(null, user);
} catch (err) {
done(err);
}
}
)
); Callback Routes
const router = new Router();
// Step 1: redirect the user to the provider.
router.get(
"/auth/google",
passport.authenticate("google", { scope: ["profile", "email"] })
);
// Step 2: provider redirects back; Passport handles the token exchange.
router.get(
"/auth/google/callback",
passport.authenticate("google", { failureRedirect: "/login" }),
async (ctx) => {
ctx.redirect("/dashboard"); // success
}
);
// GitHub — same pattern.
router.get("/auth/github", passport.authenticate("github", { scope: ["user:email"] }));
router.get(
"/auth/github/callback",
passport.authenticate("github", { failureRedirect: "/login" }),
async (ctx) => {
ctx.redirect("/dashboard");
}
); What to Store
| Field | Store? | Notes |
|---|---|---|
| Provider + provider ID | Yes | Needed to look up the user on return |
| Yes | For account linking and notifications | |
| Display name / avatar | Yes | UX only — can be re-fetched |
| Access token | Avoid | Only if you call provider APIs on behalf of the user |
| Refresh token | Avoid unless needed | Encrypt at rest if stored |
Up Next
Secure your Koa app’s HTTP responses with koa-helmet to add critical security
headers in a single middleware call.