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

OAuth 2.0 in Plain English

The valet key analogy

Some cars come with a valet key. It starts the engine and opens the doors, but it cannot open the trunk or the glove box. You hand it to the valet, and they can drive your car without accessing your personal belongings.

OAuth works the same way. When you click “Log in with GitHub,” you are not giving your GitHub password to the app. You are asking GitHub to issue a limited-access key that lets the app read your profile. The app never learns your password, and you control what it can access.

The four parties

Every OAuth flow involves four parties:

The user (you). The person who wants to log in. OAuth calls this the “resource owner” because you own the data (your GitHub profile, your email, your repos).

The app (your server). The application the user wants to log in to. OAuth calls this the “client.” It sounds backwards (your server is the client?) but it makes sense: your server is a client of GitHub’s API.

The provider (GitHub). The service that holds the user’s account and data. OAuth calls this the “authorization server” (for the login part) and the “resource server” (for the API part). In practice, these are often the same service.

The browser. The intermediary that carries the user between your app and the provider via redirects. The browser is not a formal OAuth party, but it is essential to the flow.

The flow in everyday language

Here is what happens when a user clicks “Log in with GitHub,” told as a story:

1. Your app sends the user to GitHub.

The user clicks a “Log in with GitHub” button. Your server responds with a redirect to GitHub’s authorization page. The URL includes your app’s ID (so GitHub knows which app is asking) and what information you want access to (like the user’s email and profile).

2. GitHub asks the user for permission.

GitHub shows the user a page: “This app wants to access your profile and email. Allow?” The user is on GitHub’s site, logged in with their GitHub account. Your app is not involved in this step at all.

3. The user approves.

The user clicks “Authorize.” GitHub now knows the user consents to sharing their information with your app.

4. GitHub sends the user back to your app with a code.

GitHub redirects the user’s browser back to your app, attaching a short-lived authorization code to the URL. This code is not an access token. It is a one-time voucher that your server can exchange for a token.

5. Your server exchanges the code for an access token.

Your server takes the authorization code and makes a direct HTTP request to GitHub (server-to-server, not through the browser). It sends the code along with your app’s secret. GitHub verifies everything and returns an access token.

6. Your server uses the access token to fetch the user’s profile.

Your server calls GitHub’s API (e.g. GET https://api.github.com/user) with the access token in the Authorization header. GitHub returns the user’s profile data: name, email, avatar, GitHub ID.

7. Your server creates a session.

With the user’s profile in hand, your server creates or finds a local user account, starts a session, sets a cookie, and redirects the user to your app. They are logged in.

Why the code exchange?

You might wonder: why does GitHub send back a code instead of sending the access token directly?

The code arrives in the browser’s URL (via a redirect). URLs are visible in browser history, server logs, and referrer headers. If the access token were in the URL, it could leak.

The authorization code is safe to put in the URL because it is:

  • Short-lived (typically expires in 10 minutes)
  • Single-use (can only be exchanged once)
  • Useless without the client secret (which only your server knows)

Your server exchanges the code for a token via a direct server-to-server request. The access token never touches the browser.

Why the client secret?

When you register your app with GitHub, you get two values:

  • Client ID: Public. Identifies your app. Included in the authorization URL that the user sees.
  • Client secret: Private. Proves your server is really your app. Sent only in server-to-server requests, never to the browser.

The code exchange requires the client secret. This means even if an attacker intercepts the authorization code from the URL, they cannot exchange it without your secret.

The OAuth 2.0 spec

OAuth 2.0 is defined in RFC 6749. The spec defines multiple “grant types” (different flows for different scenarios). The one we described above is the authorization code grant, which is the standard flow for server-side web applications.

Other grant types exist (implicit, client credentials, device code), but the authorization code grant is the one you will use for “Log in with GitHub/Google” and the one this course teaches.

In the next lesson, we will map this flow to the actual HTTP requests and URLs.

Why does GitHub send an authorization code back to the browser instead of sending the access token directly?

What is the difference between the client ID and the client secret?

← The Problem with Passwords The Authorization Code Flow, Step by Step →

© 2026 hectoday. All rights reserved.