Goth Providers
Expert guidance for configuring OAuth providers with github.com/markbates/goth. Focus on Google and Microsoft (Azure AD) with patterns applicable to all 70+ supported providers.
Provider Registration Pattern
Register providers at application startup using goth.UseProviders() :
import ( "github.com/markbates/goth" "github.com/markbates/goth/providers/google" "github.com/markbates/goth/providers/azureadv2" )
func init() { goth.UseProviders( google.New( os.Getenv("GOOGLE_CLIENT_ID"), os.Getenv("GOOGLE_CLIENT_SECRET"), "http://localhost:3000/auth/google/callback", "email", "profile", ), azureadv2.New( os.Getenv("AZURE_CLIENT_ID"), os.Getenv("AZURE_CLIENT_SECRET"), "http://localhost:3000/auth/microsoft/callback", azureadv2.ProviderOptions{ Tenant: azureadv2.CommonTenant, Scopes: []string{"openid", "profile", "email"}, }, ), ) }
Provider Constructor Pattern
All providers follow a similar constructor pattern:
provider.New( clientID string, // OAuth client/application ID clientSecret string, // OAuth client secret callbackURL string, // Your callback URL (must match provider config) scopes ...string, // Permission scopes to request )
Callback URL Configuration
The callback URL must:
-
Match exactly what's registered in the provider's developer console
-
Be accessible from the user's browser
-
Handle the OAuth callback response
// Development callbackURL := "http://localhost:3000/auth/google/callback"
// Production callbackURL := "https://yourdomain.com/auth/google/callback"
// Dynamic based on environment func getCallbackURL(provider string) string { baseURL := os.Getenv("BASE_URL") if baseURL == "" { baseURL = "http://localhost:3000" } return fmt.Sprintf("%s/auth/%s/callback", baseURL, provider) }
Scopes Reference
Common Scopes
Scope Purpose
openid
OpenID Connect authentication
Access user's email address
profile
Access basic profile info (name, picture)
Provider-Specific Scopes
Request only scopes needed for your application. More scopes = more user friction.
Google OAuth Setup
Console Configuration
-
Go to Google Cloud Console
-
Create project or select existing
-
Enable "Google+ API" or "People API"
-
Configure OAuth consent screen
-
Create OAuth 2.0 credentials (Web application)
-
Add authorized redirect URIs
Code Configuration
import "github.com/markbates/goth/providers/google"
google.New( os.Getenv("GOOGLE_CLIENT_ID"), os.Getenv("GOOGLE_CLIENT_SECRET"), "http://localhost:3000/auth/google/callback", "email", "profile", // Common scopes )
Google-Specific Scopes
Scope Data Access
Email address
profile
Name, picture, locale
https://www.googleapis.com/auth/calendar.readonly
Read calendars
https://www.googleapis.com/auth/drive.readonly
Read Drive files
Access User Data
user, _ := gothic.CompleteUserAuth(w, r) // user.Email - Google email // user.Name - Display name // user.AvatarURL - Profile picture // user.AccessToken - For Google API calls
For detailed Google setup steps, see references/google-oauth-setup.md .
Microsoft (Azure AD) Setup
Azure Portal Configuration
-
Go to Azure Portal
-
Navigate to Azure Active Directory → App registrations
-
Create new registration
-
Add redirect URI (Web platform)
-
Create client secret under Certificates & secrets
-
Configure API permissions
Code Configuration
import "github.com/markbates/goth/providers/azureadv2"
azureadv2.New( os.Getenv("AZURE_CLIENT_ID"), os.Getenv("AZURE_CLIENT_SECRET"), "http://localhost:3000/auth/microsoft/callback", azureadv2.ProviderOptions{ Tenant: azureadv2.CommonTenant, // or specific tenant ID Scopes: []string{ "openid", "profile", "email", }, }, )
Tenant Options
// Any Microsoft account (personal + work/school) Tenant: azureadv2.CommonTenant
// Only work/school accounts Tenant: azureadv2.OrganizationsTenant
// Only personal Microsoft accounts Tenant: azureadv2.ConsumersTenant
// Specific organization only Tenant: "your-tenant-id"
Microsoft-Specific Scopes
Scope Data Access
openid
ID token
profile
Name, preferred_username
Email address
User.Read
Full profile via Graph API
Calendars.Read
Read calendar events
Files.Read
Read OneDrive files
Access User Data
user, _ := gothic.CompleteUserAuth(w, r) // user.Email - Microsoft email // user.Name - Display name // user.UserID - Azure AD object ID // user.AccessToken - For Microsoft Graph API calls // user.IDToken - JWT with claims
For detailed Microsoft setup steps, see references/microsoft-oauth-setup.md .
Multiple Providers Pattern
Support multiple login options:
func init() { goth.UseProviders( google.New( os.Getenv("GOOGLE_CLIENT_ID"), os.Getenv("GOOGLE_CLIENT_SECRET"), getCallbackURL("google"), "email", "profile", ), azureadv2.New( os.Getenv("AZURE_CLIENT_ID"), os.Getenv("AZURE_CLIENT_SECRET"), getCallbackURL("microsoft"), azureadv2.ProviderOptions{ Tenant: azureadv2.CommonTenant, Scopes: []string{"openid", "profile", "email"}, }, ), ) }
// Login page template
const loginTemplate = <h1>Sign In</h1> <a href="/auth/google">Sign in with Google</a> <a href="/auth/microsoft">Sign in with Microsoft</a>
Provider Selection at Runtime
Get available providers:
// List all registered providers providers := goth.GetProviders() for name, provider := range providers { fmt.Printf("Provider: %s\n", name) }
// Get specific provider provider, err := goth.GetProvider("google") if err != nil { // Provider not registered }
Custom Provider Name
Override the provider name if needed:
// In your route handler gothic.GetProviderName = func(req *http.Request) (string, error) { // Extract from URL path: /auth/{provider} parts := strings.Split(req.URL.Path, "/") if len(parts) >= 3 { return parts[2], nil } return "", errors.New("no provider specified") }
Environment Variables
Organize credentials by provider:
Google OAuth
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=GOCSPX-xxx
Microsoft/Azure AD
AZURE_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx AZURE_CLIENT_SECRET=xxx~xxx AZURE_TENANT_ID=common # or specific tenant
Application
BASE_URL=http://localhost:3000 SESSION_SECRET=your-32-byte-secret
Common Issues
"redirect_uri_mismatch" Error
The callback URL doesn't match provider configuration:
-
Check exact URL including protocol (http vs https)
-
Verify trailing slashes match
-
Ensure port number is correct
-
Check for localhost vs 127.0.0.1 differences
"invalid_client" Error
Client ID or secret is wrong:
-
Verify environment variables are loaded
-
Check for extra whitespace in credentials
-
Ensure correct project/app is selected in console
"access_denied" Error
User denied permission or scopes are invalid:
-
Review requested scopes
-
Check consent screen configuration
-
Verify app is published (if Google)
Quick Reference
Task Code
Register provider goth.UseProviders(provider)
Get provider goth.GetProvider("name")
List providers goth.GetProviders()
Dynamic callback fmt.Sprintf("%s/auth/%s/callback", baseURL, provider)
Related Skills
-
goth-fundamentals - Core Goth concepts and interfaces
-
goth-echo-security - Framework integration and security
Reference Documentation
-
references/google-oauth-setup.md
-
Step-by-step Google configuration
-
references/microsoft-oauth-setup.md
-
Step-by-step Microsoft/Azure AD configuration