go-auth
Providers

GitHub

GitHub OAuth 2.0 provider — setup, configuration, scopes, email handling, and calling the sign-in flow.

GitHub

Setup

  1. Go to GitHub Developer Settings.
  2. Create an OAuth App.
  3. Set the authorization callback URL to {BaseURL}/auth/oauth/github/callback.

Configuration

import "github.com/nazimdjebloun/go-auth/provider/github"

goauth.WithProvider(github.New(github.Config{
    ClientID:     os.Getenv("GITHUB_CLIENT_ID"),     // required
    ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), // required
    RedirectURL:  "https://myapp.com/auth/oauth/github/callback", // required
    Scopes:       nil, // optional, default []string{"user:email"}
}))
FieldTypeRequiredDefaultNotes
ClientIDstringRequiredFrom your GitHub OAuth App.
ClientSecretstringRequiredFrom your GitHub OAuth App.
RedirectURLstringRequiredMust exactly match the callback URL configured in the GitHub App settings.
Scopes[]stringOptional["user:email"]Override to request additional GitHub scopes.

Email handling

GitHub's /user endpoint only returns an email when the user has set a public profile email. When it's empty, the provider falls back to /user/emails (which needs the user:email scope) and picks the address marked both primary and verified — if none qualifies, the exchange fails rather than silently using an unverified address.

When the public profile email is present, it's treated as verified without a separate check: GitHub only allows a verified address to be set as the public one, so a non-empty user.Email is verified by construction.

The display name falls back to the GitHub username (login) when the account has no display name set.

Frontend client setup

The Client example below calls the same apiRequest(baseUrl, method, path, body) helper used throughout these guides — see Client → Setup.

Signing in

Start the flow — GET /auth/oauth/github

Public. Returns GitHub's authorization URL — PKCE (S256) is always included, whether or not GitHub strictly requires it for this app. Redirect the browser there; GitHub handles the rest until it redirects back to your callback URL.

Response (200 OK): { "url": "https://github.com/login/oauth/authorize?..." }

Errors

CodeStatusCause
provider_not_found404WithProvider(github.New(...)) was never called, or EnableOAuth is false

curl

curl https://api.myapp.com/auth/oauth/github

No Origin header needed — this is a GET with no state-changing effect, so OriginCheck doesn't apply to it.


Programmatic (Go)

url, err := auth.Services.OAuth.Initiate(ctx, "github")
if err != nil {
    // *domain.AuthError — provider_not_found if the name is wrong
}
// redirect the browser to url

Client

const { url } = await apiRequest(API_BASE, "GET", "/auth/oauth/github");
window.location.href = url;

The callback — GET/POST /auth/oauth/github/callback

GitHub redirects here itself — your frontend never calls this URL directly. On success it sets session cookies and redirects the browser to {BaseURL}/auth/callback; on failure, to {BaseURL}/auth/callback?error={code}&provider=github. Your frontend route at {BaseURL}/auth/callback reads that query string to know whether to show the app or an error.

See Routes for the full parameter reference, Error Handling for every error this can redirect back with, and Guides → OAuth linking for connecting GitHub to an account that's already logged in (a different flow from the sign-in one above).

Next

  • Google — the other built-in provider
  • OAuth linking — link/unlink/list connected providers on an existing account
  • Authentication — the response shape once a session exists, regardless of how it was created

On this page