add initial auth0 module
This commit is contained in:
144
auth/auth0/README.md
Normal file
144
auth/auth0/README.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# Auth0
|
||||
|
||||
A clean, secure, and reusable Auth0 authentication module for Go web applications using **Chi** router.
|
||||
|
||||
This module provides everything you need to add Auth0-based login/logout to your Chi-based application:
|
||||
|
||||
- `/login` — Redirects user to Auth0 Universal Login
|
||||
- `/callback` — Handles Auth0 redirect, verifies ID token, stores user profile & access token in session
|
||||
- `/logout` — Clears session and redirects to Auth0 logout (full single sign-out)
|
||||
- Authentication middleware — Protects routes, redirects unauthenticated users to login
|
||||
- `CurrentUser(r *http.Request)` helper — Retrieve authenticated user claims in handlers
|
||||
|
||||
## Features
|
||||
|
||||
- Secure OAuth2/OIDC flow with state validation and CSRF protection
|
||||
- Clean functional options pattern for dependency injection
|
||||
- Easy-to-use middleware for protected routes
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/derekmwright/go-web/auth/auth0
|
||||
```
|
||||
|
||||
(Replace with your actual repo path when published)
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/yourusername/go-auth0-chi"
|
||||
// your session manager, e.g. gorilla/sessions, scollett/chi-sessions, etc.
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := chi.NewRouter()
|
||||
|
||||
// Your session manager (must implement auth0.SessionManager interface)
|
||||
sessionManager := NewYourSessionManager() // e.g. cookie store
|
||||
|
||||
// Your logger (zap, zerolog, etc. — must implement auth0.Logger)
|
||||
logger := NewYourLogger()
|
||||
|
||||
// Initialize the Auth0 module
|
||||
registerRoutes, requireAuth, err := auth0.New(
|
||||
auth0.WithLogger(logger),
|
||||
auth0.WithSessions(sessionManager),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Mount the auth routes (usually under root or /auth)
|
||||
registerRoutes(r)
|
||||
|
||||
// Public routes
|
||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("Home page — public"))
|
||||
})
|
||||
|
||||
// Protected routes
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(requireAuth) // ← enforces authentication
|
||||
|
||||
r.Get("/dashboard", func(w http.ResponseWriter, r *http.Request) {
|
||||
user := auth0.CurrentUser(r)
|
||||
// user is map[string]any with Auth0 claims (sub, name, email, etc.)
|
||||
w.Write([]byte("Welcome to the dashboard!"))
|
||||
})
|
||||
|
||||
r.Get("/profile", func(w http.ResponseWriter, r *http.Request) {
|
||||
profile := auth0.CurrentUser(r).(map[string]any)
|
||||
// Render profile...
|
||||
})
|
||||
})
|
||||
|
||||
log.Println("Server starting on :8080")
|
||||
http.ListenAndServe(":8080", r)
|
||||
}
|
||||
```
|
||||
|
||||
## Routes Added
|
||||
|
||||
When you call `registerRoutes(r)`, the following routes are registered:
|
||||
|
||||
| Route | Method | Purpose |
|
||||
|-------------|--------|---------|
|
||||
| `/login` | GET | Initiates login: generates state, stores in session, redirects to Auth0 |
|
||||
| `/callback` | GET | Auth0 redirect URI: validates state, exchanges code, verifies ID token, stores user & access token in session, redirects to `/` |
|
||||
| `/logout` | GET | Clears session and redirects to Auth0 `/v2/logout` with proper `returnTo` and `client_id` (full SSO logout) |
|
||||
|
||||
You can mount these under a subrouter if preferred:
|
||||
|
||||
```go
|
||||
authRouter := chi.NewRouter()
|
||||
registerRoutes(authRouter)
|
||||
r.Mount("/auth", authRouter) // → /auth/login, /auth/callback, etc.
|
||||
```
|
||||
|
||||
## Required Environment Variables
|
||||
|
||||
The module reads Auth0 configuration from environment variables:
|
||||
|
||||
```env
|
||||
AUTH0_DOMAIN=your-tenant.auth0.com
|
||||
AUTH0_CLIENT_ID=your-client-id
|
||||
AUTH0_CLIENT_SECRET=your-client-secret
|
||||
AUTH0_REDIRECT_URI=http://localhost:8080/callback
|
||||
```
|
||||
|
||||
Make sure `AUTH0_REDIRECT_URI` is listed in your Auth0 Application → **Allowed Callback URLs**.
|
||||
|
||||
Also add your post-logout URL (e.g. `http://localhost:8080/`) to **Allowed Logout URLs** in the Auth0 dashboard.
|
||||
|
||||
## Dependencies Injected
|
||||
|
||||
You must provide:
|
||||
|
||||
- `Logger` — with `Debug`, `Info`, `Error` methods (easy to adapt zap, zerolog, log/slog, etc.)
|
||||
- `SessionManager` — with `Get(ctx, key)` and `Put(ctx, key, value)` (compatible with gorilla/sessions, etc.)
|
||||
|
||||
## Session Storage
|
||||
|
||||
The module stores:
|
||||
|
||||
- `"user"` → `map[string]any` with decoded ID token claims (sub, name, email, picture, etc.)
|
||||
- `"access_token"` → raw access token string (useful for calling APIs)
|
||||
|
||||
You can extend this as needed in your own handlers.
|
||||
|
||||
## Testing
|
||||
|
||||
The module is designed for easy testing — all dependencies are interfaces. See the `_test.go` files for examples using mocks.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user