TL;DR: OAuth 2.0 is the protocol behind social login. Your app redirects the user to Google/GitHub, they log in there, and Google sends your app a code. Your app exchanges that code for an access token that proves the user's identity. Libraries like NextAuth.js handle this entire flow for you — you just need a Client ID and Client Secret from the OAuth provider.

What Is OAuth?

OAuth 2.0 (Open Authorization) is a protocol that lets a user grant a third-party application limited access to their account on another service — without sharing their password. It is the standard behind every "Sign in with Google/GitHub/Apple" button.

The key insight: the user never gives your app their Google password. They log in to Google directly. Google then tells your app: "yes, this user is who they say they are, and they have authorized your app to read their basic profile." Your app never sees the Google credentials.

The OAuth Flow (Step by Step)

1
User clicks "Sign in with Google" — your app redirects to Google's OAuth URL with your Client ID and requested scopes (e.g., profile, email)
2
User logs in to Google — on Google's page, not yours. Google shows what access your app is requesting.
3
User approves — Google redirects back to your app's callback URL with a temporary authorization code
4
Your server exchanges the code — your backend sends the code + your Client Secret to Google's token endpoint
5
Google returns an access token — your app uses this to call Google's API and get the user's profile (name, email, avatar)
6
Your app creates a session — you find or create the user in your database and create your own session/JWT

OAuth in Next.js with NextAuth.js

NextAuth.js (now Auth.js) handles all 6 steps above. You configure it once:

// src/auth.ts (NextAuth v5 / Auth.js)
import NextAuth from 'next-auth'
import Google from 'next-auth/providers/google'
import GitHub from 'next-auth/providers/github'

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],
  // Optional: link OAuth identity to your DB user
  callbacks: {
    async session({ session, token }) {
      session.user.id = token.sub
      return session
    },
  },
})
// .env.local
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-secret
GITHUB_ID=your-github-app-id
GITHUB_SECRET=your-github-secret
NEXTAUTH_SECRET=a-random-32-char-string  # openssl rand -base64 32
NEXTAUTH_URL=http://localhost:3000
// Sign in button in any component
import { signIn } from '@/auth'

export function SignInButton() {
  return (
    <form action={async () => { 'use server'; await signIn('google') }}>
      <button type="submit">Sign in with Google</button>
    </form>
  )
}

Getting OAuth Credentials

Google

  1. Go to console.cloud.google.com
  2. Create a project → APIs & Services → Credentials
  3. Create OAuth 2.0 Client ID (Web application)
  4. Add http://localhost:3000/api/auth/callback/google as an authorized redirect URI
  5. Copy the Client ID and Client Secret to your .env.local

GitHub

  1. Go to github.com/settings/developers
  2. New OAuth App
  3. Set Authorization callback URL to http://localhost:3000/api/auth/callback/github
  4. Generate a client secret and copy both to .env.local

What AI Gets Wrong About OAuth

  • Wrong callback URL: AI sometimes generates callback URLs that don't match what you register with the provider. The exact URL must match.
  • Missing NEXTAUTH_URL in production: NextAuth needs this set to your production domain — AI often forgets to mention the production env var setup.
  • Exposing Client Secret: The Client Secret must never appear in frontend code or be committed to Git. Only the Client ID is public-safe.
  • Not linking to database users: AI sometimes sets up OAuth without storing the user in your database, so you cannot associate data with them across sessions.

What to Learn Next

Next Step

For most vibe coder projects, OAuth via NextAuth is the right auth choice — you skip building login/signup forms, password hashing, and reset flows entirely. Users log in with an account they already trust. Set it up once and move on to building the actual product.

FAQ

OAuth 2.0 is an authorization framework that lets users grant third-party applications limited access to their accounts on another service without sharing their password. It is the protocol behind "Sign in with Google," "Sign in with GitHub," and similar social login buttons.

OAuth 2.0 handles authorization (granting access to resources). OpenID Connect (OIDC) is built on top of OAuth and handles authentication (proving identity). When you use "Sign in with Google," you are using OpenID Connect, which uses OAuth underneath. Libraries like NextAuth handle both automatically.

Not deeply. Libraries like NextAuth.js for Next.js handle the OAuth flow for you. You configure your OAuth credentials (Client ID and Secret from Google/GitHub) and the library handles redirects, token exchange, and session management.

An access token is a short-lived credential (typically valid for 1 hour) your app receives after OAuth completes. It proves the user granted access and lets your app call the provider's API on their behalf. Access tokens are paired with refresh tokens for obtaining new access tokens without re-prompting the user.

Install NextAuth.js, create a Google OAuth app at console.cloud.google.com to get a Client ID and Client Secret, add them to your .env.local, configure NextAuth with the Google provider, and add a sign-in button to your UI. NextAuth handles the entire OAuth flow.