feat: migrate auth0mock from Node.js to Go
Refactor the application to a Go-based architecture for improved performance and maintainability. Replace the Dockerfile to utilize a multi-stage build process, enhancing image efficiency. Implement comprehensive session store tests to ensure reliability and create new OAuth handlers for managing authentication efficiently. Update documentation to reflect these structural changes.
This commit is contained in:
@@ -4,64 +4,88 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
auth0mock is a Node.js/Express application that simulates an Auth0 authentication server for local development. It provides OAuth 2.0 and OpenID Connect (OIDC) endpoints compatible with the Auth0 API, allowing developers to test authentication flows without connecting to the actual Auth0 service.
|
||||
auth0mock is a Go application that simulates an Auth0 authentication server for local development. It provides OAuth 2.0 and OpenID Connect (OIDC) endpoints compatible with the Auth0 API, allowing developers to test authentication flows without connecting to the actual Auth0 service.
|
||||
|
||||
## Development Commands
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
yarn install
|
||||
# Build the service
|
||||
go build -o auth0mock ./cmd/service
|
||||
|
||||
# Start production server (port 3333)
|
||||
yarn start
|
||||
# Run the service
|
||||
go run ./cmd/service
|
||||
|
||||
# Development with auto-reload (nodemon)
|
||||
yarn dev
|
||||
# Run tests
|
||||
go test ./... -v
|
||||
|
||||
# Run tests with coverage
|
||||
go test ./... -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
# Format code
|
||||
yarn lintfix
|
||||
gofumpt -w .
|
||||
goimports -w .
|
||||
|
||||
# Check formatting
|
||||
yarn lint
|
||||
# Run pre-commit hooks
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
This is a single-file Express application (`app.js`) that implements:
|
||||
```
|
||||
auth0mock/
|
||||
├── cmd/service/ # Entry point, HTTP server setup, configuration
|
||||
├── auth/ # JWT/JWK generation and signing, PKCE verification
|
||||
├── handlers/ # HTTP handlers for all endpoints
|
||||
│ └── templates/ # Embedded HTML templates (login form)
|
||||
├── store/ # In-memory session and user storage
|
||||
├── public/ # Static files (favicon)
|
||||
├── k8s/ # Kubernetes deployment manifests
|
||||
└── Dockerfile # Multi-stage Go build
|
||||
```
|
||||
|
||||
**Authentication Endpoints:**
|
||||
**Key Packages:**
|
||||
- `auth/jwt.go` - RSA key generation, JWT signing using lestrrat-go/jwx/v2
|
||||
- `auth/pkce.go` - PKCE verification (S256 and plain methods)
|
||||
- `store/sessions.go` - Thread-safe session storage with TTL and cleanup
|
||||
- `store/users.go` - Thread-safe user storage with JSON file loading
|
||||
- `handlers/oauth.go` - OAuth token exchange, authorization, code generation
|
||||
- `handlers/discovery.go` - OIDC discovery and JWKS endpoints
|
||||
- `handlers/management.go` - Auth0 Management API endpoints
|
||||
|
||||
- `POST /oauth/token` - Token exchange (OAuth 2.0 authorization code flow)
|
||||
## HTTP Endpoints
|
||||
|
||||
**Authentication:**
|
||||
- `POST /oauth/token` - Token exchange (authorization code and client_credentials)
|
||||
- `GET /authorize` - Authorization endpoint with HTML login form
|
||||
- `POST /code` - Code generation for PKCE flow
|
||||
|
||||
**Discovery Endpoints:**
|
||||
|
||||
**Discovery:**
|
||||
- `GET /.well-known/openid-configuration` - OIDC discovery document
|
||||
- `GET /.well-known/jwks.json` - JSON Web Key Set for token verification
|
||||
|
||||
**Management API (Auth0-compatible):**
|
||||
- `GET /.well-known/jwks.json` - JSON Web Key Set
|
||||
|
||||
**Management API:**
|
||||
- `GET /api/v2/users-by-email` - Get user by email
|
||||
- `POST /api/v2/users` - Create user
|
||||
- `PATCH /api/v2/users/:userid` - Update user
|
||||
- `PATCH /api/v2/users/{userid}` - Update user
|
||||
- `POST /api/v2/tickets/password-change` - Password change ticket
|
||||
|
||||
**Key Implementation Details:**
|
||||
|
||||
- RSA 2048-bit key pair generated at startup using `node-jose`
|
||||
- In-memory session and user storage (not persistent)
|
||||
- PKCE support with code challenge verification
|
||||
- Custom claims for admin (`https://unbound.se/admin`) and email (`https://unbound.se/email`)
|
||||
**Session:**
|
||||
- `GET /userinfo` - User information
|
||||
- `POST /tokeninfo` - Decode JWT token
|
||||
- `GET /v2/logout` - Logout and session cleanup
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| ------------ | -------------------------- | -------------------------------- |
|
||||
| `ISSUER` | `localhost:3333` | JWT issuer claim |
|
||||
| `AUDIENCE` | `https://generic-audience` | JWT audience claim |
|
||||
| `USERS_FILE` | `./users.json` | Path to initial users JSON file |
|
||||
| `DEBUG` | (unset) | Debug logging (`app*` to enable) |
|
||||
| Variable | Default | Purpose |
|
||||
|----------|---------|---------|
|
||||
| `PORT` | `3333` | HTTP listen port |
|
||||
| `ISSUER` | `localhost:3333` | JWT issuer (without https://) |
|
||||
| `AUDIENCE` | `https://generic-audience` | JWT audience |
|
||||
| `USERS_FILE` | `./users.json` | Path to initial users JSON file |
|
||||
| `ADMIN_CUSTOM_CLAIM` | `https://unbound.se/admin` | Admin custom claim key |
|
||||
| `EMAIL_CUSTOM_CLAIM` | `https://unbound.se/email` | Email custom claim key |
|
||||
| `LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |
|
||||
| `LOG_FORMAT` | `text` | Log format (text, json) |
|
||||
|
||||
## Initial Users
|
||||
|
||||
@@ -78,6 +102,14 @@ Create a `users.json` file to seed users on startup:
|
||||
}
|
||||
```
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
- RSA 2048-bit key pair generated at startup using `lestrrat-go/jwx/v2`
|
||||
- In-memory session storage with 5-minute TTL and automatic cleanup
|
||||
- Proper PKCE verification (S256 method with SHA256 hash)
|
||||
- Thread-safe stores using `sync.RWMutex`
|
||||
- Graceful shutdown with signal handling
|
||||
|
||||
## Integration with Shiny
|
||||
|
||||
This service is used for local development and acceptance testing of the Shiny platform. The gateway and frontend services are configured to accept tokens signed by this mock server when running locally.
|
||||
|
||||
Reference in New Issue
Block a user