hectoday
DocsCoursesChangelog GitHub
DocsCoursesChangelog GitHub

Access Required

Enter your access code to view courses.

Invalid code

← All courses OAuth and Social Login

Why OAuth?

  • The Problem with Passwords
  • OAuth 2.0 in Plain English
  • The Authorization Code Flow, Step by Step
  • Project Setup

GitHub Login

  • Register a GitHub OAuth App
  • The Authorization Redirect
  • The State Parameter
  • The Callback Handler
  • Fetching the User Profile
  • Creating or Linking Accounts
  • The Complete Flow

Google Login

  • Register a Google OAuth App
  • Building Google Login

Production Concerns

  • Multiple Providers, One User
  • Combining OAuth with Password Auth
  • Error Handling
  • Logout and Token Cleanup
  • Common Mistakes
  • Capstone: Multi-Provider Login Page

The Complete Flow

Everything in one place

Over the last six lessons, we built GitHub login piece by piece. This lesson puts it all together so you can see the complete picture.

The files

src/
  app.ts              # routes, hooks
  server.ts           # starts the server
  env.ts              # environment variables
  db.ts               # User type, store, findOrCreateFromGithub
  sessions.ts         # session store
  cookies.ts          # cookie helpers
  auth.ts             # authenticate function
  oauth-state.ts      # CSRF state management
  github.ts           # GitHub API calls
  routes/
    github.ts         # GET /auth/github, GET /auth/github/callback

The data flow

User clicks "Log in with GitHub"
│
├─ GET /auth/github
│   └─ Generate state, store it
│   └─ Redirect to GitHub with client_id, redirect_uri, scope, state
│
├─ User approves on GitHub
│
├─ GET /auth/github/callback?code=...&state=...
│   ├─ Verify state (CSRF protection)
│   ├─ POST github.com/login/oauth/access_token
│   │   └─ Send code + client_secret → receive access_token
│   ├─ GET api.github.com/user (with access_token)
│   │   └─ Receive profile: id, name, avatar
│   ├─ GET api.github.com/user/emails (with access_token)
│   │   └─ Receive emails, pick primary verified
│   ├─ findOrCreateFromGithub(profile)
│   │   └─ Find by GitHub ID or create new user
│   ├─ createSession(user.id)
│   │   └─ Store session in server-side Map
│   └─ Redirect to / with Set-Cookie header
│
├─ User is now logged in
│
└─ GET /me
    ├─ Read session ID from cookie
    ├─ Look up session → find user
    └─ Return user profile

What stays on the server

The access token never leaves your server. The client secret never leaves your server. The session ID travels in a cookie, but the session data stays on the server. The only thing the browser sees is the authorization code (briefly, in a redirect URL) and the session cookie.

What you understand now

If you followed along and built each piece, you now understand:

  • What OAuth is and why it exists (delegated authentication)
  • The authorization code flow (redirect, consent, code, token exchange)
  • Why the code exchange exists (keep the access token off the browser)
  • Why the state parameter exists (prevent CSRF on the callback)
  • How to call a provider’s API with an access token
  • How to create local users from provider profiles
  • How OAuth login connects to sessions (the same mechanism as password auth)

This is the same flow that every “Log in with GitHub” button on the internet uses. The libraries (Passport.js, NextAuth, Auth.js) wrap these exact HTTP calls. Now you know what they do internally.

What is next

In Section 3, we add Google as a second provider. This will show you how the pattern repeats: different URLs and different API responses, but the same flow. We will also handle the case where a user signs up with GitHub and later tries Google with the same email (account linking).

Exercises

Exercise 1: Open your browser’s network tab and walk through the entire flow, logging every request. Count the redirects. Identify which requests are browser-to-server, which are browser-to-GitHub, and which are server-to-GitHub.

Exercise 2: Add a logout route if you have not already. The pattern is the same as the auth course: POST /logout, delete the session, clear the cookie. Verify the full cycle: login, view /me, logout, verify /me returns 401, login again (returning user path).

Exercise 3: Try the flow with a GitHub account that has no public email. Verify that the email comes from the /user/emails endpoint instead. Check the server logs or add a console.log to confirm which email source was used.

After the OAuth flow completes, what mechanism keeps the user logged in on subsequent requests?

← Creating or Linking Accounts Register a Google OAuth App →

© 2026 hectoday. All rights reserved.