xiaohongshu
xiaohongshu
goth-providers
This skill should be used when the user asks to "add a provider", "configure google oauth", "set up microsoft login", "azure ad authentication", "oauth provider setup", "add social login", or needs help with specific OAuth provider configuration in Goth.
Full skill instructions
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.
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"},
},
),
)
}
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
)
The callback URL must:
// 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)
}
| Scope | Purpose |
|---|---|
openid | OpenID Connect authentication |
email | Access user's email address |
profile | Access basic profile info (name, picture) |
Request only scopes needed for your application. More scopes = more user friction.
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
)
| Scope | Data Access |
|---|---|
email | 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 |
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.
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",
},
},
)
// 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"
| Scope | Data Access |
|---|---|
openid | ID token |
profile | Name, preferred_username |
email | Email address |
User.Read | Full profile via Graph API |
Calendars.Read | Read calendar events |
Files.Read | Read OneDrive files |
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.
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>
`
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
}
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")
}
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
The callback URL doesn't match provider configuration:
Client ID or secret is wrong:
User denied permission or scopes are invalid:
| 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) |
references/google-oauth-setup.md - Step-by-step Google configurationreferences/microsoft-oauth-setup.md - Step-by-step Microsoft/Azure AD configurationxiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience