Stop 08 · Authentication Across the StackTopics · 3/8

OAuth 2.0 & Social Login

Part of the Full Stack Developer Roadmap

In short

'Continue with Google' gets more signups than yet another password form. Under the hood it's OAuth 2.0: the user proves who they are to Google, and Google vouches for them to your app.

Letting users sign up or log in with an existing Google or GitHub account instead of creating a new password — reducing signup friction across your full-stack app.

The mascot hands a signed letter to a small friend who collects a parcel at a counter.

Think of it like this

The authority letter for your parcel

You can't reach the post office, so you send your younger cousin with a signed authority letter. The clerk checks it and hands over that one parcel. Your cousin never gets your ID card or bank passbook, only what the letter allows.

Watch it happen

Login with Google, step by step

Browser
Your API
Google

GET /auth/google

1/8The user clicks 'Continue with Google'.

The big ideas

What you need to know

The secret stays on the server

The client secret is used only in the server-to-server token call. It must never appear in React code.

state and PKCE stop forgery

A random state value, plus PKCE, makes sure the code that comes back belongs to the login you started.

Link by provider id

Store Google's sub claim on the user. Emails can change, sub stays the same for that Google account.

Use a library

Auth.js, Passport or your framework's auth module handle the redirects and checks. Learn the flow, then don't hand-roll it.

See it in code

Walk through the code

ts
1app.get("/auth/google/callback", async (req, res) => {2  if (req.query.state !== req.session.oauthState) return res.status(400).send("Bad state");3  const tokenRes = await fetch("https://oauth2.googleapis.com/token", { method: "POST",4    body: new URLSearchParams({5      code: String(req.query.code),6      client_id: process.env.GOOGLE_CLIENT_ID!,7      client_secret: process.env.GOOGLE_CLIENT_SECRET!,8      redirect_uri: "http://localhost:4000/auth/google/callback",9      grant_type: "authorization_code",10    }),11  });12  const { id_token } = await tokenRes.json();13  const profile = await verifyGoogleIdToken(id_token); // e.g. with google-auth-library14  const user = await upsertUser({ googleId: profile.sub, email: profile.email });15  req.session.userId = user.id; res.redirect("http://localhost:5173/dashboard");16});

1/4Reject the callback unless the state matches what you saved before redirecting.

This is the heart of the flow. In a real app, a library like Auth.js or Passport writes most of this for you.

Save yourself the pain

Common mistakes

Oops

Doing the code-for-token exchange in the React app with the client secret in the bundle.

Do this instead

Do the exchange on your server. Anyone can read a secret that ships to the browser.

Oops

Using the Google access token as your app's login session.

Do this instead

Use Google only to identify the user once, then issue your own session or token for your API.

Your mission

Add 'Continue with GitHub'

~45 min

Quick check

Why does Google send back a short-lived code instead of the tokens directly in the redirect URL?

Go deeper

  1. 1Implement 'Sign in with Google' end-to-end, from the frontend button through to a backend session/token.
  2. 2Learn the OAuth authorization code flow at a conceptual level.
  3. 3Handle the case where a social login email matches an existing local account.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge