go-auth
Providers

Providers

OAuth providers built into go-auth, and how registering one works.

Providers

An OAuth provider is anything implementing port.OAuthProvider — three methods: Name() string, AuthURL(state, codeChallenge string) string, and Exchange(ctx, code, codeVerifier string) (*port.OAuthProfile, error). Register one with WithProvider and its routes (GET /auth/oauth/{provider}, GET/POST /auth/oauth/{provider}/callback, POST /auth/oauth/{provider}/link, POST /auth/oauth/{provider}/unlink, GET /auth/oauth/providers) are mounted when authentication OAuth is enabled — see Routes → OAuth. You can register more than one provider at once; each needs a unique Name().

OAuth routes exist when AuthenticationConfig.OAuth is true with a configured provider. Enabling OAuth without a provider fails startup. Registration OAuth separately controls new account creation.

Every built-in provider uses PKCE (S256) regardless of whether the provider strictly requires it: go-auth generates the verifier, stores it alongside a single-use oauth_state token, and hands it to Exchange on the callback — see Security for why that matters.

Currently built in: GitHub and Google. More can be added the same way provider/github and provider/google are built — implementing port.OAuthProvider against any OAuth2 provider's token and userinfo endpoints.

Setup

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

goauth.WithAuthentication(goauth.AuthenticationConfig{EmailPassword: true, OAuth: true}),
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
}))

Available providers

ProviderImport pathSetup
GitHubgithub.com/nazimdjebloun/go-auth/provider/githubGitHub
Googlegithub.com/nazimdjebloun/go-auth/provider/googleGoogle

How sign-in works

  1. The frontend calls GET /auth/oauth/{provider}, which returns the authorization URL as JSON ({ "url": ... }) — the frontend navigates the browser there itself.
  2. The provider redirects back to GET/POST /auth/oauth/{provider}/callback with code and state.
  3. go-auth checks the single-use state token, exchanges the code (PKCE verifier attached), and looks up the provider account by provider + provider user ID — never by email alone.
  4. Known provider account → verification/2FA checks, then session: cookies are set and the browser ends up at {BaseURL}/auth/callback. No token ever travels in the URL.
  5. Unknown account → a new user is created (in the same transaction as the provider link) when registration OAuth and AllowPublic are true, or a valid OAuth signup invitation is being redeemed. If the email already belongs to another account, the callback fails with email_already_exists (409): go-auth never auto-links a provider onto a possibly-different person's account. The user signs into the existing account through an enabled method, then connects the provider explicitly.
  6. RequireEmailVerification with an unverified email diverts to the verification flow instead of issuing a session; banned users are rejected.

Linking, unlinking, connected accounts

Connecting a provider to an already-logged-in account, removing one, and listing what's connected are covered in Guides → OAuth linking — the callback route is the same one as login, with a different outcome. Two notes that bite:

  • Unlinking is blocked when the provider is the account's last login method (cannot_unlink_last_provider) — set a password first via Security → Set a password.
  • OAuth-only accounts have no password hash; the set-password flow is two-step (POST /auth/set-password/request, then /confirm).

Next

On this page