OAuth

Fix GitHub OAuth Errors

Updated April 2026

Reading this article? Verify your fix in real-time. Debug your GitHub OAuth error โ†’ OAuthFixer

GitHub OAuth has two systems โ€” OAuth Apps and GitHub Apps โ€” with different capabilities and configurations. Most errors come from wrong callback URL registration, expired authorization codes, or scope mismatches.

OAuth App vs GitHub App โ€” which to use

OAuth AppGitHub App
Acts asA userItself (bot identity)
AccessUser's resourcesInstallation resources
Best forSign in with GitHub, user data accessCI/CD, repo automation
PKCE supportโœ… Yes (recommended)โœ… Yes

Common error 1 โ€” redirect_uri_mismatch

# GitHub OAuth App settings:
# github.com โ†’ Settings โ†’ Developer Settings โ†’ OAuth Apps โ†’ Your App
# Authorization callback URL must EXACTLY match your redirect_uri

# Wrong
Authorization callback URL: https://yourapp.com/  # trailing slash
redirect_uri in code: https://yourapp.com/callback  # no match

# Right โ€” both must match exactly
Authorization callback URL: https://yourapp.com/callback
redirect_uri in code: https://yourapp.com/callback

Common error 2 โ€” code expired

GitHub authorization codes expire after 10 minutes. Exchange the code immediately after the redirect:

// callback page โ€” exchange immediately
const { code } = new URLSearchParams(window.location.search);
if (code) { // Do this NOW โ€” do not wait, do not store the code const tokens = await exchangeCodeForToken(code);
}

Common error 3 โ€” scope not granted

# Request scopes in the authorization URL
const authUrl = "https://github.com/login/oauth/authorize?" + new URLSearchParams({ client_id: CLIENT_ID, redirect_uri: "https://yourapp.com/callback", scope: "user:email repo",  // request what you need state: generateState(),
});

Token exchange โ€” must be server-side

# GitHub token exchange requires client_secret
# NEVER do this in browser-side JavaScript

# Server-side (Node.js)
const response = await fetch("https://github.com/login/oauth/access_token", { method: "POST", headers: { "Accept": "application/json", "Content-Type": "application/json", }, body: JSON.stringify({ client_id: process.env.GITHUB_CLIENT_ID, client_secret: process.env.GITHUB_CLIENT_SECRET, code: authorizationCode, redirect_uri: "https://yourapp.com/callback", }),
});
const { access_token } = await response.json();

PKCE with GitHub (recommended for SPAs)

# GitHub supports PKCE for OAuth Apps โ€” use it for SPAs
const authUrl = "https://github.com/login/oauth/authorize?" + new URLSearchParams({ client_id: CLIENT_ID, code_challenge: challenge, code_challenge_method: "S256", redirect_uri: "https://yourapp.com/callback",
});
Debug your GitHub OAuth error โ†’ OAuthFixer