echogoog

package
v0.0.0-...-8ee3720 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 24, 2026 License: MIT Imports: 12 Imported by: 0

README ΒΆ

Google OpenID Echo Middleware - Complete Implementation

Go Reference

A comprehensive Echo middleware for Google OpenID Connect authentication with Google Workspace hosted domain restrictions.

Repository: github.com/presbrey/pkg/echogoog

πŸš€ Installation

go get github.com/presbrey/pkg/echogoog

πŸ“¦ Quick Start

import (
    "github.com/labstack/echo/v4"
    "github.com/presbrey/pkg/echogoog"
)

func main() {
    e := echo.New()

    // Configure Google OpenID middleware
    mw := echogoog.NewMiddleware(&echogoog.Config{
        ClientID:             "your-client-id.apps.googleusercontent.com",
        ClientSecret:         "your-client-secret",
        RedirectPath:         "/auth/google/callback",
        AllowedHostedDomains: []string{"example.com"},
    })

    // Register authentication routes
    mw.RegisterRoutes(e)

    // Protect routes requiring authentication
    e.GET("/dashboard", dashboardHandler, mw.RequireAuth())

    e.Start(":8080")
}

πŸ“¦ Package Structure

github.com/presbrey/pkg/echogoog/
β”œβ”€β”€ middleware.go      # Main implementation
β”œβ”€β”€ go.mod            # Module dependencies
β”œβ”€β”€ go.sum            # Dependency checksums
β”œβ”€β”€ README.md         # This file
└── example/
    └── main.go       # Complete usage example

View Source:


πŸ”‘ Key Features

  1. Hosted Domain Restriction - Restrict authentication to specific Google Workspace domains
  2. Secure by Default - HTTP-only cookies, CSRF protection, ID token verification
  3. Easy Integration - Simple Echo middleware pattern
  4. Fully Configurable - Customize paths, cookies, redirects, and handlers
  5. Type-Safe - Access user info with strongly-typed structs
  6. Production Ready - Comprehensive error handling and validation

πŸ“ Configuration Options

Option Type Default Description
ClientID string required Google OAuth2 client ID
ClientSecret string required Google OAuth2 client secret
RedirectURL string required* OAuth2 callback URL (static)
RedirectPath string required* OAuth2 callback path (dynamic) - generates full URL from request context
TrustForwardedHeaders bool false Trust X-Forwarded-* and Forwarded headers (only enable behind trusted proxy)
AllowedRedirectHosts []string nil Allowed hostnames for redirect URL generation (restricts host spoofing)
AllowedHostedDomains []string nil List of allowed Google Workspace domains
Scopes []string ["openid", "email", "profile"] OAuth2 scopes to request
SessionCookieName string "google_openid_session" Session cookie name
SessionMaxAge int 86400 Session cookie max age (seconds)
CookieSecure bool false Set Secure flag on cookies
CookieHTTPOnly bool true Set HttpOnly flag (always true)
CookieSameSite http.SameSite Lax SameSite cookie attribute
LoginPath string "/auth/google/login" Login initiation path
CallbackPath string "/auth/google/callback" OAuth2 callback path
LogoutPath string "/auth/google/logout" Logout path
SuccessRedirect string "/" Redirect URL after successful auth
UnauthorizedHandler echo.HandlerFunc nil Custom unauthorized handler

* Either RedirectURL or RedirectPath is required, but not both.


πŸ”„ Dynamic vs Static Redirect URLs

The middleware supports two ways to configure the OAuth2 callback URL:

Static RedirectURL

Use a fixed, absolute URL that doesn't change:

RedirectURL: "https://example.com/auth/google/callback"

Best for single-domain applications with a known URL.

Dynamic RedirectPath

Use a relative path that generates the full URL from the incoming request:

RedirectPath: "/auth/google/callback"

The middleware automatically detects:

  • Scheme: http or https (from TLS or forwarded headers when trusted)
  • Host: From request Host header (or X-Forwarded-Host/Forwarded when trusted)
  • Path: Your configured path (normalized with leading /)

Benefits:

  • Works seamlessly with multiple domains (e.g., production, staging, development)
  • Automatically adapts to proxy/load balancer schemes
  • No hardcoded URLs - perfect for containerized/cloud deployments
  • Simplifies configuration across different environments

Security Configuration:

When using RedirectPath, you should configure:

  • TrustForwardedHeaders: Set to true ONLY if behind a trusted proxy/load balancer
  • AllowedRedirectHosts: Restrict allowed hostnames to prevent host header spoofing
RedirectPath: "/auth/google/callback",
TrustForwardedHeaders: true, // Only if behind trusted proxy
AllowedRedirectHosts: []string{"example.com", "staging.example.com"},

Example: When using RedirectPath: "/auth/google/callback":

  • Request to http://localhost:8080 β†’ Callback: http://localhost:8080/auth/google/callback
  • Request to https://example.com β†’ Callback: https://example.com/auth/google/callback
  • Behind proxy with X-Forwarded-Proto β†’ Uses forwarded scheme (if TrustForwardedHeaders enabled)

πŸ” Security Features

  • βœ… CSRF protection with cryptographically random state parameter
  • βœ… ID token cryptographic verification using Google's public keys
  • βœ… HTTP-only secure cookies to prevent XSS attacks
  • βœ… Hosted domain validation from ID token claims
  • βœ… SameSite cookie protection against CSRF
  • βœ… Automatic token expiration handling
  • βœ… Host header validation and sanitization
  • βœ… RFC7239 Forwarded header support with opt-in trust model
  • βœ… Thread-safe per-request OAuth2 config (no data races)
  • βœ… Multi-value header parsing (comma-separated)

πŸ“Š User Information Structure

type UserInfo struct {
    Sub           string `json:"sub"`            // Google user ID (unique)
    Email         string `json:"email"`          // Email address
    EmailVerified bool   `json:"email_verified"` // Email verification status
    Name          string `json:"name"`           // Full name
    Picture       string `json:"picture"`        // Profile picture URL
    GivenName     string `json:"given_name"`     // First name
    FamilyName    string `json:"family_name"`    // Last name
    HostedDomain  string `json:"hd"`             // Google Workspace domain
}

🎯 Domain Restriction Details

The middleware validates the hd (hosted domain) claim in the Google ID token:

  • Only Google Workspace accounts have a hosted domain
  • Personal Gmail accounts (@gmail.com) don't have this claim
  • Domain comparison is case-insensitive
  • If AllowedHostedDomains is empty, any Google account can authenticate
  • Users from unauthorized domains receive a 403 Forbidden error

Important: The domain check happens server-side using the verified ID token, not just the email address, ensuring it cannot be spoofed.


πŸ’‘ Best Practices

  1. Use HTTPS in production - Set CookieSecure: true
  2. Rotate session secrets - Implement session key rotation for long-running apps
  3. Set appropriate session timeout - Balance security and user experience
  4. Monitor failed auth attempts - Log and alert on authorization failures
  5. Implement rate limiting - Prevent brute force attacks on auth endpoints
  6. Use environment variables - Never commit credentials to source control

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

This section is empty.

Types ΒΆ

type Config ΒΆ

type Config struct {
	// ClientID is the Google OAuth2 client ID
	ClientID string

	// ClientSecret is the Google OAuth2 client secret
	ClientSecret string

	// RedirectURL is the callback URL for OAuth2 flow
	// Either RedirectURL or RedirectPath must be provided
	RedirectURL string

	// RedirectPath is the callback path for OAuth2 flow (alternative to RedirectURL)
	// When set, the absolute URL is generated dynamically from the request's scheme and host
	// Example: "/auth/google/callback" becomes "https://example.com/auth/google/callback"
	RedirectPath string

	// TrustForwardedHeaders controls whether to trust X-Forwarded-* and Forwarded headers
	// SECURITY: Only enable when behind a trusted proxy/load balancer that sets these headers
	// Default: false (for security)
	TrustForwardedHeaders bool

	// AllowedRedirectHosts is an optional list of allowed hostnames for redirect URL generation
	// When set, only these hosts are allowed when using RedirectPath
	// Example: ["example.com", "staging.example.com", "localhost:8080"]
	// Default: empty (allows any host - use with caution)
	AllowedRedirectHosts []string

	// AllowedHostedDomains is a list of Google Workspace domains allowed to authenticate
	// Example: ["example.com", "company.org"]
	AllowedHostedDomains []string

	// Scopes are the OAuth2 scopes to request (default: openid, email, profile)
	Scopes []string

	// SessionCookieName is the name of the session cookie (default: "google_openid_session")
	SessionCookieName string

	// SessionMaxAge is the max age of the session cookie in seconds (default: 86400 = 24 hours)
	SessionMaxAge int

	// CookieSecure sets the Secure flag on cookies (should be true in production)
	CookieSecure bool

	// CookieHTTPOnly sets the HttpOnly flag on cookies (default: true)
	CookieHTTPOnly bool

	// CookieSameSite sets the SameSite attribute for cookies (default: Lax)
	CookieSameSite http.SameSite

	// LoginPath is the path where users initiate login (default: "/auth/google/login")
	LoginPath string

	// CallbackPath is the path for the OAuth2 callback (default: "/auth/google/callback")
	CallbackPath string

	// LogoutPath is the path for logout (default: "/auth/google/logout")
	LogoutPath string

	// UnauthorizedHandler is called when authentication fails
	UnauthorizedHandler echo.HandlerFunc

	// SuccessRedirect is the URL to redirect to after successful authentication
	SuccessRedirect string
}

Config holds the configuration for the Google OpenID middleware

type Middleware ΒΆ

type Middleware struct {
	// contains filtered or unexported fields
}

Middleware manages Google OpenID authentication

func New ΒΆ

func New(config *Config) (*Middleware, error)

New creates a new Google OpenID middleware with the given configuration

func (*Middleware) Protect ΒΆ

func (m *Middleware) Protect() echo.MiddlewareFunc

Protect returns an Echo middleware that requires authentication

func (*Middleware) RegisterRoutes ΒΆ

func (m *Middleware) RegisterRoutes(e *echo.Echo)

RegisterRoutes registers the authentication routes on the Echo instance

type UserInfo ΒΆ

type UserInfo struct {
	Sub           string `json:"sub"`
	Email         string `json:"email"`
	EmailVerified bool   `json:"email_verified"`
	Name          string `json:"name"`
	Picture       string `json:"picture"`
	GivenName     string `json:"given_name"`
	FamilyName    string `json:"family_name"`
	HostedDomain  string `json:"hd"` // Google Workspace domain
}

UserInfo represents the authenticated user's information

func GetUser ΒΆ

func GetUser(c echo.Context) (*UserInfo, error)

GetUser retrieves the authenticated user from the request context

Directories ΒΆ

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL