Claude-skill-registry goth-fundamentals
This skill should be used when the user asks to "set up goth", "install goth", "oauth in go", "authentication in golang", "goth package", "goth basics", or mentions "github.com/markbates/goth". Provides foundational guidance for the Goth multi-provider authentication library.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/goth-fundamentals" ~/.claude/skills/majiayu000-claude-skill-registry-goth-fundamentals && rm -rf "$T"
skills/data/goth-fundamentals/SKILL.mdGoth Fundamentals
Expert guidance for github.com/markbates/goth - a Go library providing simple, clean, idiomatic multi-provider OAuth authentication.
Installation
Install the package:
go get github.com/markbates/goth
Import in code:
import ( "github.com/markbates/goth" "github.com/markbates/goth/gothic" "github.com/markbates/goth/providers/google" )
Core Concepts
Provider Interface
Every authentication provider implements the
goth.Provider interface:
type Provider interface { Name() string BeginAuth(state string) (Session, error) UnmarshalSession(string) (Session, error) FetchUser(Session) (User, error) Debug(bool) RefreshToken(refreshToken string) (*oauth2.Token, error) RefreshTokenAvailable() bool }
Key methods:
- Returns provider identifier (e.g., "google", "microsoft")Name()
- Initiates OAuth flow, returns session with auth URLBeginAuth()
- Retrieves user data after successful authenticationFetchUser()
- Obtains new access token using refresh tokenRefreshToken()
Session Interface
Sessions manage OAuth state throughout the authentication flow:
type Session interface { GetAuthURL() (string, error) Authorize(Provider, Params) (string, error) Marshal() string }
User Struct
Authenticated user data returned after successful OAuth:
type User struct { RawData map[string]interface{} Provider string Email string Name string FirstName string LastName string NickName string Description string UserID string AvatarURL string Location string AccessToken string AccessTokenSecret string RefreshToken string ExpiresAt time.Time IDToken string }
Gothic Helper Package
The
gothic package provides convenience functions for common web frameworks:
Key Functions
// Begin authentication - redirects to provider gothic.BeginAuthHandler(res http.ResponseWriter, req *http.Request) // Complete authentication - handles callback gothic.CompleteUserAuth(res http.ResponseWriter, req *http.Request) (goth.User, error) // Get user from session (if already authenticated) gothic.GetFromSession(providerName string, req *http.Request) (string, error) // Logout user gothic.Logout(res http.ResponseWriter, req *http.Request) error
Provider Selection
Gothic uses the
provider query parameter or URL path segment to identify which provider to use:
// Query parameter: /auth?provider=google // Path segment: /auth/google
Override the provider getter if needed:
gothic.GetProviderName = func(req *http.Request) (string, error) { return mux.Vars(req)["provider"], nil }
Basic Authentication Flow
Step 1: Register Providers
Initialize providers at application startup:
func init() { goth.UseProviders( google.New( os.Getenv("GOOGLE_CLIENT_ID"), os.Getenv("GOOGLE_CLIENT_SECRET"), "http://localhost:3000/auth/google/callback", "email", "profile", ), ) }
Step 2: Create Auth Routes
func main() { http.HandleFunc("/auth/", handleAuth) http.HandleFunc("/auth/callback/", handleCallback) http.HandleFunc("/logout", handleLogout) http.ListenAndServe(":3000", nil) } func handleAuth(w http.ResponseWriter, r *http.Request) { gothic.BeginAuthHandler(w, r) } func handleCallback(w http.ResponseWriter, r *http.Request) { user, err := gothic.CompleteUserAuth(w, r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // User authenticated - store in session, redirect, etc. fmt.Fprintf(w, "Welcome %s!", user.Name) } func handleLogout(w http.ResponseWriter, r *http.Request) { gothic.Logout(w, r) http.Redirect(w, r, "/", http.StatusTemporaryRedirect) }
Step 3: Configure Session Store
Gothic uses gorilla/sessions by default:
import "github.com/gorilla/sessions" func init() { key := os.Getenv("SESSION_SECRET") maxAge := 86400 * 30 // 30 days isProd := os.Getenv("ENV") == "production" store := sessions.NewCookieStore([]byte(key)) store.MaxAge(maxAge) store.Options.Path = "/" store.Options.HttpOnly = true store.Options.Secure = isProd gothic.Store = store }
Environment Variables Pattern
Store OAuth credentials securely using environment variables:
# .env (never commit this file) GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-client-secret MICROSOFT_CLIENT_ID=your-azure-app-id MICROSOFT_CLIENT_SECRET=your-azure-secret SESSION_SECRET=your-32-byte-random-string
Load with godotenv or similar:
import "github.com/joho/godotenv" func init() { godotenv.Load() }
Supported Providers (70+)
Goth includes providers for major platforms:
| Category | Providers |
|---|---|
| Cloud/Enterprise | Google, Microsoft (Azure AD), Apple, Amazon, Okta, Auth0 |
| Development | GitHub, GitLab, Bitbucket, Gitea |
| Social | Facebook, Twitter, Instagram, LinkedIn, Discord |
| Productivity | Slack, Salesforce, Shopify, Zoom |
| Other | Spotify, Twitch, PayPal, Stripe, Uber |
Import provider packages individually:
import ( "github.com/markbates/goth/providers/google" "github.com/markbates/goth/providers/azureadv2" "github.com/markbates/goth/providers/github" )
Error Handling
Handle common authentication errors:
user, err := gothic.CompleteUserAuth(w, r) if err != nil { switch { case strings.Contains(err.Error(), "access_denied"): // User denied access http.Redirect(w, r, "/login?error=denied", http.StatusTemporaryRedirect) case strings.Contains(err.Error(), "invalid_grant"): // Token expired or revoked http.Redirect(w, r, "/login?error=expired", http.StatusTemporaryRedirect) default: // Log and show generic error log.Printf("Auth error: %v", err) http.Error(w, "Authentication failed", http.StatusInternalServerError) } return }
Token Refresh
For long-lived sessions, refresh tokens before expiry:
func refreshIfNeeded(provider goth.Provider, user *goth.User) error { if !provider.RefreshTokenAvailable() { return nil } if time.Until(user.ExpiresAt) > 5*time.Minute { return nil // Token still valid } token, err := provider.RefreshToken(user.RefreshToken) if err != nil { return err } user.AccessToken = token.AccessToken user.RefreshToken = token.RefreshToken user.ExpiresAt = token.Expiry return nil }
Quick Reference
| Task | Function/Pattern |
|---|---|
| Register providers | |
| Start auth flow | |
| Complete auth | |
| Logout | |
| Get current provider | |
| Configure session store | |
| Access user data | , , |
Related Skills
- goth-providers - Detailed provider configuration (Google, Microsoft)
- goth-echo-security - Echo framework integration and security patterns