Files
golib/hwsauth/doc.go
Haelnorr bdae21ec0b Updated documentation for JWT, HWS, and HWSAuth packages.
- Updated JWT README.md with proper format and version number
- Updated HWS README.md and created comprehensive doc.go
- Updated HWSAuth README.md and doc.go with proper environment variable documentation
- All documentation now follows GOLIB rules format

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-13 13:37:37 +11:00

213 lines
6.6 KiB
Go

// Package hwsauth provides JWT-based authentication middleware for the hws web framework.
//
// # Overview
//
// hwsauth integrates with the hws web server to provide secure, stateless authentication
// using JSON Web Tokens (JWT). It supports both access and refresh tokens, automatic
// token rotation, and flexible transaction handling compatible with any database or ORM.
//
// # Key Features
//
// - JWT-based authentication with access and refresh tokens
// - Automatic token rotation and refresh
// - Generic over user model and transaction types
// - ORM-agnostic transaction handling
// - Environment variable configuration
// - Middleware for protecting routes
// - Context-based user retrieval
// - Optional SSL cookie security
//
// # Quick Start
//
// First, define your user model:
//
// type User struct {
// UserID int
// Username string
// Email string
// }
//
// func (u User) ID() int {
// return u.UserID
// }
//
// Configure the authenticator using environment variables or programmatically:
//
// // Option 1: Load from environment variables
// cfg, err := hwsauth.ConfigFromEnv()
// if err != nil {
// log.Fatal(err)
// }
//
// // Option 2: Create config manually
// cfg := &hwsauth.Config{
// SSL: true,
// TrustedHost: "https://example.com",
// SecretKey: "your-secret-key",
// AccessTokenExpiry: 5, // 5 minutes
// RefreshTokenExpiry: 1440, // 1 day
// TokenFreshTime: 5, // 5 minutes
// LandingPage: "/dashboard",
// }
//
// Create the authenticator:
//
// // Define how to begin transactions
// beginTx := func(ctx context.Context) (hwsauth.DBTransaction, error) {
// return db.BeginTx(ctx, nil)
// }
//
// // Define how to load users from the database
// loadUser := func(ctx context.Context, tx *sql.Tx, id int) (User, error) {
// var user User
// err := tx.QueryRowContext(ctx, "SELECT id, username, email FROM users WHERE id = ?", id).
// Scan(&user.UserID, &user.Username, &user.Email)
// return user, err
// }
//
// // Create the authenticator
// auth, err := hwsauth.NewAuthenticator[User, *sql.Tx](
// cfg,
// loadUser,
// server,
// beginTx,
// logger,
// errorPage,
// )
// if err != nil {
// log.Fatal(err)
// }
//
// # Middleware
//
// Use the Authenticate middleware to protect routes:
//
// // Apply to all routes
// server.AddMiddleware(auth.Authenticate())
//
// // Ignore specific paths
// auth.IgnorePaths("/login", "/register", "/public")
//
// Use route guards for specific protection requirements:
//
// // LoginReq: Requires user to be authenticated
// protectedHandler := auth.LoginReq(myHandler)
//
// // LogoutReq: Redirects authenticated users (for login/register pages)
// loginHandler := auth.LogoutReq(loginPageHandler)
//
// // FreshReq: Requires fresh authentication (for sensitive operations)
// changePasswordHandler := auth.FreshReq(changePasswordHandler)
//
// # Login and Logout
//
// To log a user in:
//
// func loginHandler(w http.ResponseWriter, r *http.Request) {
// // Validate credentials...
// user := getUserFromDatabase(username)
//
// // Log the user in (sets JWT cookies)
// err := auth.Login(w, r, user, rememberMe)
// if err != nil {
// // Handle error
// }
//
// http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
// }
//
// To log a user out:
//
// func logoutHandler(w http.ResponseWriter, r *http.Request) {
// tx, _ := db.BeginTx(r.Context(), nil)
// defer tx.Rollback()
//
// err := auth.Logout(tx, w, r)
// if err != nil {
// // Handle error
// }
//
// tx.Commit()
// http.Redirect(w, r, "/", http.StatusSeeOther)
// }
//
// # Retrieving the Current User
//
// Access the authenticated user from the request context:
//
// func dashboardHandler(w http.ResponseWriter, r *http.Request) {
// user := auth.CurrentModel(r.Context())
// if user.ID() == 0 {
// // User not authenticated
// return
// }
//
// fmt.Fprintf(w, "Welcome, %s!", user.Username)
// }
//
// # ORM Support
//
// hwsauth works with any ORM that implements the DBTransaction interface.
//
// GORM Example:
//
// beginTx := func(ctx context.Context) (hwsauth.DBTransaction, error) {
// return gormDB.WithContext(ctx).Begin().Statement.ConnPool.(*sql.Tx), nil
// }
//
// loadUser := func(ctx context.Context, tx *gorm.DB, id int) (User, error) {
// var user User
// err := tx.First(&user, id).Error
// return user, err
// }
//
// auth, err := hwsauth.NewAuthenticator[User, *gorm.DB](...)
//
// Bun Example:
//
// beginTx := func(ctx context.Context) (hwsauth.DBTransaction, error) {
// return bunDB.BeginTx(ctx, nil)
// }
//
// loadUser := func(ctx context.Context, tx bun.Tx, id int) (User, error) {
// var user User
// err := tx.NewSelect().Model(&user).Where("id = ?", id).Scan(ctx)
// return user, err
// }
//
// auth, err := hwsauth.NewAuthenticator[User, bun.Tx](...)
//
// # Environment Variables
//
// The following environment variables are supported when using ConfigFromEnv:
//
// - HWSAUTH_SSL: Enable SSL secure cookies (default: false)
// - HWSAUTH_TRUSTED_HOST: Full server address for SSL (required if SSL is true)
// - HWSAUTH_SECRET_KEY: Secret key for signing JWT tokens (required)
// - HWSAUTH_ACCESS_TOKEN_EXPIRY: Access token expiry in minutes (default: 5)
// - HWSAUTH_REFRESH_TOKEN_EXPIRY: Refresh token expiry in minutes (default: 1440)
// - HWSAUTH_TOKEN_FRESH_TIME: Token fresh time in minutes (default: 5)
// - HWSAUTH_LANDING_PAGE: Redirect destination for authenticated users (default: "/profile")
// - HWSAUTH_DATABASE_TYPE: Database type - postgres, mysql, sqlite, mariadb (default: "postgres")
// - HWSAUTH_DATABASE_VERSION: Database version string (default: "15")
// - HWSAUTH_JWT_TABLE_NAME: Custom JWT blacklist table name (default: "jwtblacklist")
//
// # Security Considerations
//
// - Always use SSL in production (set HWSAUTH_SSL=true)
// - Use strong, randomly generated secret keys
// - Set appropriate token expiry times based on your security requirements
// - Use FreshReq middleware for sensitive operations (password changes, etc.)
// - Store refresh tokens securely in HTTP-only cookies
//
// # Type Parameters
//
// hwsauth uses Go generics for type safety:
//
// - T Model: Your user model type (must implement the Model interface)
// - TX DBTransaction: Your transaction type (must implement DBTransaction interface)
//
// This allows compile-time type checking and eliminates the need for type assertions
// when working with your user models.
package hwsauth