goauthx
A comprehensive, production-ready authentication and authorization library for Go. Framework-agnostic, supports multiple databases (MySQL, PostgreSQL, SQL Server), and provides JWT-based authentication with role-based access control (RBAC).
Features
- ✅ User Authentication: Registration, login, logout, and password management
- ✅ JWT Tokens: Secure access tokens with refresh token support
- ✅ Google OAuth: Sign in with Google account integration
- ✅ Role-Based Access Control (RBAC): Flexible roles and permissions system
- ✅ Email Verification: Built-in email verification system
- ✅ Password Reset: Secure password reset with tokens
- ✅ Pre-built HTTP Handlers: Ready-to-use REST API handlers
- ✅ Configurable Routes: Customize API endpoint paths
- ✅ Multiple Database Support: MySQL, PostgreSQL, and SQL Server
- ✅ Framework Agnostic: Works with
net/http, Echo, Fiber, Gin, and others
- ✅ Production Ready: Comprehensive error handling, logging, and testing
- ✅ Migration System: Built-in database migration tool
- ✅ Middleware Support: Ready-to-use HTTP middleware for authentication and authorization
Quick Start
Installation
go get github.com/devchuckcamp/goauthx
Basic Usage
package main
import (
"context"
"log"
"time"
"github.com/devchuckcamp/goauthx"
)
func main() {
// 1. Configure the library
cfg := goauthx.DefaultConfig()
cfg.Database = goauthx.DatabaseConfig{
Driver: goauthx.Postgres,
DSN: "postgres://user:password@localhost:5432/authdb?sslmode=disable",
}
cfg.JWT.Secret = "your-super-secret-jwt-key-min-32-chars-long"
// 2. Create the store
store, err := goauthx.NewStore(cfg.Database)
if err != nil {
log.Fatal(err)
}
defer store.Close()
// 3. Run migrations
migrator := goauthx.NewMigrator(store, cfg.Database.Driver)
if err := migrator.Up(context.Background()); err != nil {
log.Fatal(err)
}
// 4. Create the auth service
authService, err := goauthx.NewService(cfg, store)
if err != nil {
log.Fatal(err)
}
// 5. Register a user
resp, err := authService.Register(context.Background(), goauthx.RegisterRequest{
Email: "user@example.com",
Password: "securepassword123",
FirstName: "John",
LastName: "Doe",
})
if err != nil {
log.Fatal(err)
}
log.Printf("User registered: %s", resp.User.Email)
log.Printf("Access token: %s", resp.AccessToken)
}
Running Migrations
Use the CLI tool to manage database migrations:
# Build the migration tool
cd cmd/goauthx-migrate
go build
# Apply migrations
./goauthx-migrate --dsn "postgres://user:pass@localhost/dbname?sslmode=disable" --driver postgres up
# Check migration status
./goauthx-migrate --dsn "..." --driver postgres status
# Rollback last migration
./goauthx-migrate --dsn "..." --driver postgres down
Using Pre-built HTTP Handlers
package main
import (
"context"
"log"
"net/http"
"github.com/devchuckcamp/goauthx"
)
func main() {
// Setup configuration, store, and service...
cfg := goauthx.DefaultConfig()
// ... configure database and JWT settings ...
store, _ := goauthx.NewStore(cfg.Database)
defer store.Close()
// Run migrations
migrator := goauthx.NewMigrator(store, cfg.Database.Driver)
migrator.Up(context.Background())
authService, _ := goauthx.NewService(cfg, store)
// Create HTTP handlers with default routes
mux := http.NewServeMux()
handlers := goauthx.NewHandlers(authService, nil)
handlers.RegisterRoutes(mux)
// All authentication endpoints are now available:
// POST /auth/register
// POST /auth/login
// POST /auth/logout (authenticated)
// POST /auth/refresh
// GET /auth/profile (authenticated)
// POST /auth/change-password (authenticated)
// POST /auth/forgot-password
// POST /auth/reset-password
// POST /auth/verify-email
// POST /auth/resend-verification (authenticated)
// GET /auth/google - Google OAuth login
// GET /auth/google/callback - Google OAuth callback
// POST /auth/google/unlink - Unlink Google account (authenticated)
http.ListenAndServe(":8080", mux)
}
Using Custom Routes
// Customize endpoint paths
routeConfig := goauthx.DefaultRouteConfig()
routeConfig.RegisterPath = "/api/v1/register"
routeConfig.LoginPath = "/api/v1/login"
routeConfig.ProfilePath = "/api/v1/me"
handlers := goauthx.NewHandlers(authService, routeConfig)
handlers.RegisterRoutes(mux)
Using Custom Middleware
package main
import (
"net/http"
"github.com/devchuckcamp/goauthx"
)
func main() {
// Setup (cfg, store, authService)...
authMiddleware := goauthx.NewAuthMiddleware(authService)
mux := http.NewServeMux()
// Use pre-built handlers for auth endpoints
handlers := goauthx.NewHandlers(authService, nil)
handlers.RegisterRoutes(mux)
// Add custom protected routes
mux.Handle("/api/profile", authMiddleware.Authenticate(
http.HandlerFunc(profileHandler),
))
// Admin only routes
mux.Handle("/api/admin", authMiddleware.Authenticate(
authMiddleware.RequireRole("admin")(
http.HandlerFunc(adminHandler),
),
))
http.ListenAndServe(":8080", mux)
}
Supported Databases
PostgreSQL
cfg.Database = goauthx.DatabaseConfig{
Driver: goauthx.Postgres,
DSN: "postgres://user:password@localhost:5432/dbname?sslmode=disable",
}
MySQL
cfg.Database = goauthx.DatabaseConfig{
Driver: goauthx.MySQL,
DSN: "user:password@tcp(localhost:3306)/dbname?parseTime=true",
}
SQL Server
cfg.Database = goauthx.DatabaseConfig{
Driver: goauthx.SQLServer,
DSN: "sqlserver://user:password@localhost:1433?database=dbname",
}
Configuration
Full Configuration Example
cfg := &goauthx.Config{
Database: goauthx.DatabaseConfig{
Driver: goauthx.Postgres,
DSN: "postgres://...",
MaxOpenConns: 25,
MaxIdleConns: 5,
ConnMaxLifetime: 5 * time.Minute,
},
JWT: goauthx.JWTConfig{
Secret: "your-secret-min-32-chars",
AccessTokenExpiry: 15 * time.Minute,
Issuer: "my-app",
Audience: "my-app-users",
},
Password: goauthx.PasswordConfig{
MinLength: 8,
BcryptCost: 12,
},
Token: goauthx.TokenConfig{
RefreshTokenExpiry: 7 * 24 * time.Hour, // 7 days
RefreshTokenLength: 64,
},
OAuth: goauthx.OAuthConfig{
Google: goauthx.GoogleOAuthConfig{
: "your-google-client-id",
ClientSecret: "your-google-client-secret",
RedirectURL: "http://localhost:8080/auth/google/callback",
Enabled: true,
},
},
}
Google OAuth Integration
Setup
-
Get Google OAuth Credentials:
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable Google+ API
- Go to "Credentials" → "Create Credentials" → "OAuth 2.0 Client ID"
- Add authorized redirect URIs (e.g.,
http://localhost:8080/auth/google/callback)
- Copy Client ID and Client Secret
-
Configure goauthx:
cfg := goauthx.DefaultConfig()
cfg.OAuth.Google.ClientId = "your-client-id"
cfg.OAuth.Google.ClientSecret = "your-client-secret"
cfg.OAuth.Google.RedirectURL = "http://localhost:8080/auth/google/callback"
cfg.OAuth.Google.Enabled = true
- Using Pre-built Handlers (Recommended):
handlers := goauthx.NewHandlers(authService, nil)
handlers.RegisterRoutes(mux)
// OAuth endpoints are automatically available:
// GET /auth/google - Initiates Google OAuth flow
// GET /auth/google/callback - Handles OAuth callback
// POST /auth/google/unlink - Unlinks Google account (authenticated)
Usage Flows
New User Registration via Google:
- User clicks "Sign in with Google"
- Redirect to
/auth/google
- User authenticates with Google
- Google redirects to
/auth/google/callback
- New user account is automatically created
- User receives JWT access and refresh tokens
Existing User Login via Google:
- User with existing account clicks "Sign in with Google"
- OAuth flow completes
- Google account is linked to existing user
- User receives JWT tokens
Linking Google to Existing Account:
- Users can link their Google account after registration
- If email matches, accounts are automatically linked
- Email is marked as verified if Google account is verified
Testing
# Start OAuth flow
curl http://localhost:8080/auth/google
# User will be redirected to Google login page
# After authentication, Google redirects to callback with tokens
# Response includes JWT access token and refresh token
# Unlink Google account (requires authentication)
curl -X POST http://localhost:8080/auth/google/unlink \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"account_id": "oauth-account-id"}'
Security Features
- CSRF Protection: State parameter for OAuth flow
- Account Linking: Prevents duplicate accounts
- Password Optional: Users can sign up with only Google
- Safe Unlinking: Can't unlink last auth method
- Token Management: Automatic OAuth token refresh
Core Concepts
Authentication
- Register: Create new user accounts with email and password
- Login: Authenticate users and issue JWT access tokens
- Logout: Revoke refresh tokens
- Refresh: Generate new access tokens using refresh tokens
Authorization
- Roles: Group permissions (e.g., "admin", "user", "moderator")
- Permissions: Granular access control (e.g., "posts:read", "posts:write")
- User-Role Assignment: Users can have multiple roles
- Role-Permission Assignment: Roles can have multiple permissions
Checking Permissions
// Check if user has a role
hasRole, err := authService.HasRole(ctx, userID, "admin")
// Check if user has a permission
hasPerm, err := authService.HasPermission(ctx, userID, "posts:write")
// Get all user permissions
permissions, err := authService.GetUserPermissions(ctx, userID)
Email Verification
// During registration, create verification token
token, err := authService.ResendVerificationEmail(ctx, userID)
// In production: send token via email to user
// User verifies email with token
err := authService.VerifyEmail(ctx, token)
Password Reset
// User requests password reset
token, err := authService.RequestPasswordReset(ctx, "user@example.com")
// In production: send token via email to user
// User resets password with token
err := authService.ResetPassword(ctx, goauthx.ResetPasswordRequest{
Token: token,
NewPassword: "newSecurePassword123",
})
Change Password
// User changes password (requires authentication)
err := authService.ChangePassword(ctx, userID, goauthx.ChangePasswordRequest{
OldPassword: "currentPassword",
NewPassword: "newSecurePassword123",
})
Testing with Docker
Quick Start with Docker PostgreSQL
- Start the PostgreSQL database:
docker-compose up -d
This will start a PostgreSQL 16 container with:
- Database:
authdb
- User:
authdb
- Password:
authdb
- Port:
5432
- Run the example application:
cd examples/with-handlers
go run main.go
The example app will automatically:
- Connect to the database
- Run all migrations
- Start the HTTP server on
:8080
- Test the API endpoints:
Register a new user:
curl -X POST http://localhost:8080/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123",
"first_name": "John",
"last_name": "Doe"
}'
Login:
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123"
}'
Access protected profile (replace YOUR_TOKEN with the access_token from login):
curl -X GET http://localhost:8080/auth/profile \
-H "Authorization: Bearer YOUR_TOKEN"
Change password (authenticated):
curl -X POST http://localhost:8080/auth/change-password \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"old_password": "securepassword123",
"new_password": "newSecurePassword456"
}'
Request password reset:
curl -X POST http://localhost:8080/auth/forgot-password \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'
Reset password with token:
curl -X POST http://localhost:8080/auth/reset-password \
-H "Content-Type: application/json" \
-d '{
"token": "RESET_TOKEN_FROM_EMAIL",
"new_password": "newSecurePassword456"
}'
- Stop the database:
docker-compose down
For more Docker commands and troubleshooting, see DOCKER.md.
Examples
See the examples/ directory for a complete working example:
examples/with-handlers/ - Complete example using pre-built HTTP handlers
Documentation
For detailed documentation, see the docs/ directory:
License
MIT License - see LICENSE for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please open an issue on GitHub.