OAuth Module
The OAuth module adds social login and single sign-on capabilities to your application. Users can authenticate with their existing Google, GitHub, Microsoft, or Discord accounts. It supports the full OAuth 2.0 authorization code flow with optional PKCE (Proof Key for Code Exchange) for enhanced security, account linking to connect multiple providers to a single user, and both stateless JWT and server-side session auth modes.
Capabilities​
- Multiple Providers — Google, GitHub, Microsoft, and Discord out of the box. Each provider can be independently enabled/disabled without removing its configuration.
- PKCE (Proof Key for Code Exchange) — Optional per-provider PKCE support prevents authorization code interception attacks. Enabled by default. Particularly important for mobile and SPA clients.
- Account Linking — When enabled, if a user authenticates via OAuth with an email that already exists in your system, the OAuth identity is linked to the existing account rather than creating a duplicate.
- Account Unlinking — Users can disconnect an OAuth provider from their account via
DELETE /oauth/{provider}, giving them control over linked identities. - Automatic Signup — New users can be created automatically from OAuth profile data (email, name, avatar). Controlled via
AllowSignup. - Provider Token Storage — Optionally store the provider's access and refresh tokens (e.g., to call Google APIs on behalf of the user) via
StoreProviderTokens. - Trust Email Verification — When enabled, trusts the OAuth provider's email verification status and marks the user's email as verified in GoAuth.
- Dual Auth Mode — Works with both Stateless (JWT) and Session auth modules. Set
UseSessionAuth: trueto create server-side sessions instead of issuing JWTs. - Frontend Redirect or JSON — Configurable
DefaultRedirectURLfor SPA flows (tokens in URL fragment) or JSON response for API-first clients. - Error Redirect — Configurable
ErrorRedirectURLfor graceful error handling in the frontend. - Custom Storage — Pass custom
CoreStorage,OAuthStorage, andSessionStorageimplementations. - Provider Discovery —
GET /oauth/providerslists all configured providers.GET /oauth/linkedshows the authenticated user's linked providers.
Supported Providers​
Google, GitHub, Microsoft, Discord.
Registration​
import (
"github.com/bete7512/goauth/pkg/modules/oauth"
"github.com/bete7512/goauth/pkg/config"
)
a.Use(oauth.New(&config.OAuthModuleConfig{
Providers: map[string]*config.OAuthProviderConfig{
"google": {
ClientID: os.Getenv("GOOGLE_CLIENT_ID"),
ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"),
PKCE: true,
Enabled: true,
},
"github": {
ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
Enabled: true,
},
},
DefaultRedirectURL: "http://localhost:3000/auth/callback",
ErrorRedirectURL: "http://localhost:3000/auth/error",
AllowSignup: true,
AllowAccountLinking: true,
TrustEmailVerification: true,
StoreProviderTokens: false,
UseSessionAuth: false, // true to use sessions instead of JWT
}, nil))
The second argument to oauth.New is *oauth.OAuthStorageOptions -- pass nil to use the shared storage from deps.Storage.
Important: The OAuth module requires APIURL in your config for callback URL construction:
a, _ := auth.New(&config.Config{
APIURL: "https://api.yourapp.com",
// ...
})
Configuration​
OAuthModuleConfig​
type OAuthModuleConfig struct {
Providers map[string]*OAuthProviderConfig
DefaultRedirectURL string // Frontend callback URL (tokens in URL fragment)
ErrorRedirectURL string // Frontend error URL
AllowSignup bool // Create new users via OAuth (default: true)
AllowAccountLinking bool // Link OAuth to existing email accounts (default: true)
TrustEmailVerification bool // Trust provider's email verified status (default: true)
StateTTL time.Duration // State token validity (default: 10min)
StoreProviderTokens bool // Store provider access/refresh tokens (default: false)
UseSessionAuth bool // Use sessions instead of JWT (default: false)
}
OAuthProviderConfig​
type OAuthProviderConfig struct {
ClientID string
ClientSecret string
Scopes []string // Uses provider defaults if empty
RedirectURL string // Override callback URL (auto-generated if empty)
PKCE bool // Proof Key for Code Exchange (default: true)
Enabled bool // Allows disabling without removing config
}
Default scopes per provider​
| Provider | Default Scopes |
|---|---|
openid, email, profile | |
| GitHub | user:email, read:user |
| Microsoft | openid, email, profile, User.Read |
| Discord | identify, email |
Custom storage​
Pass *oauth.OAuthStorageOptions as the second argument to oauth.New to override storage:
oauth.New(oauthCfg, &oauth.OAuthStorageOptions{
CoreStorage: customCoreStorage, // optional
OAuthStorage: customOAuthStorage, // optional
SessionStorage: customSessionStorage, // optional, only needed if UseSessionAuth=true
})
Endpoints​
| Method | Path | Middleware | Description |
|---|---|---|---|
| GET | /oauth/{provider} | -- | Start OAuth flow, redirects to provider |
| GET | /oauth/{provider}/callback | -- | Handle OAuth callback |
| DELETE | /oauth/{provider} | Auth | Unlink OAuth account |
| GET | /oauth/providers | -- | List configured providers |
| GET | /oauth/linked | Auth | List user's linked providers |
Flow​
- Frontend redirects user to
GET /oauth/google - GoAuth redirects to Google's consent screen (with PKCE challenge if enabled)
- Google redirects back to
GET /oauth/google/callback - GoAuth creates/links user account
- If
DefaultRedirectURLis set: redirects toDefaultRedirectURL#access_token=xxx&refresh_token=xxx - If
DefaultRedirectURLis empty: returns JSONAuthResponse
Error handling​
If ErrorRedirectURL is set, auth failures redirect to ErrorRedirectURL?error=xxx&error_description=xxx. Otherwise a JSON error response is returned.
Extensibility​
Custom Storage​
Pass *oauth.OAuthStorageOptions as the second argument to oauth.New() to override any or all storage backends:
a.Use(oauth.New(oauthCfg, &oauth.OAuthStorageOptions{
CoreStorage: myUserStore, // implements types.CoreStorage
OAuthStorage: myOAuthStore, // implements types.OAuthStorage
SessionStorage: mySessionStore, // implements types.SessionStorage (only if UseSessionAuth=true)
}))
When nil, all storage is obtained from the shared storage layer during initialization.
Provider Token Access​
When StoreProviderTokens: true, the OAuth module stores the provider's access token (and refresh token, if available) alongside the linked account record. This enables your application to make API calls to the OAuth provider on behalf of the user (e.g., accessing Google Calendar, GitHub repositories).
Dependencies​
- Core -- requires core module for user storage and authentication.
Events​
The OAuth module does not subscribe to or emit any events.