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.
52
65%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./plugins/goth-oauth/skills/goth-providers/SKILL.mdExpert 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 callsFor 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 claimsFor 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-secretThe 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 configuration88571a6
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.