mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-14 17:54:42 +00:00
Documentation updates (#236)
Remove vague or flowery language, use Simplified Technical English whenever possible
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Docker Guide
|
||||
# Docker guide
|
||||
|
||||
This document covers Docker deployment, configuration, and troubleshooting for
|
||||
The Biergarten App.
|
||||
@@ -16,7 +16,7 @@ The project uses Docker Compose to orchestrate multiple services:
|
||||
See the [deployment diagram](diagrams-out/deployment.svg) for visual
|
||||
representation.
|
||||
|
||||
## Docker Compose Environments
|
||||
## Docker Compose environments
|
||||
|
||||
### 1. Development (`docker-compose.dev.yaml`)
|
||||
|
||||
@@ -66,7 +66,7 @@ docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml down -v
|
||||
|
||||
### 2. Testing (`docker-compose.test.yaml`)
|
||||
|
||||
**Purpose**: Automated CI/CD testing in isolated environment
|
||||
**Purpose**: Automated CI/CD testing in an isolated environment
|
||||
|
||||
**Features**:
|
||||
|
||||
@@ -128,18 +128,15 @@ api.core # Production API
|
||||
docker compose --env-file web/.env.prod -f web/docker-compose.prod.yaml up -d
|
||||
```
|
||||
|
||||
## Service Dependencies
|
||||
## Service dependencies
|
||||
|
||||
Docker Compose manages startup order using health checks:
|
||||
|
||||
```mermaid
|
||||
sqlserver (health check)
|
||||
↓
|
||||
database.migrations (completes successfully)
|
||||
↓
|
||||
database.seed (completes successfully)
|
||||
↓
|
||||
api.core / tests (start when ready)
|
||||
graph TD
|
||||
A[sqlserver: health check passes] --> B[database.migrations: completes successfully]
|
||||
B --> C[database.seed: completes successfully]
|
||||
C --> D[api.core / tests: start when ready]
|
||||
```
|
||||
|
||||
**Health Check Example** (SQL Server):
|
||||
@@ -168,7 +165,7 @@ api.core:
|
||||
|
||||
## Volumes
|
||||
|
||||
### Persistent Volumes
|
||||
### Persistent volumes
|
||||
|
||||
**Development**:
|
||||
|
||||
@@ -184,7 +181,7 @@ api.core:
|
||||
- `sqlserverdata-prod` - Production database files
|
||||
- `nuget-cache-prod` - Production NuGet cache
|
||||
|
||||
### Mounted Volumes
|
||||
### Mounted volumes
|
||||
|
||||
**Test Results**:
|
||||
|
||||
@@ -203,7 +200,7 @@ Each environment uses isolated bridge networks:
|
||||
- `testnet` - Testing network (fully isolated)
|
||||
- `prodnet` - Production network
|
||||
|
||||
## Environment Variables
|
||||
## Environment variables
|
||||
|
||||
All containers are configured via environment variables from `.env` files:
|
||||
|
||||
@@ -224,9 +221,9 @@ environment:
|
||||
|
||||
For complete list, see [Environment Variables](environment-variables.md).
|
||||
|
||||
## Common Commands
|
||||
## Common commands
|
||||
|
||||
### View Services
|
||||
### View services
|
||||
|
||||
```bash
|
||||
# Running services
|
||||
@@ -236,7 +233,7 @@ docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml ps
|
||||
docker ps -a
|
||||
```
|
||||
|
||||
### View Logs
|
||||
### View logs
|
||||
|
||||
```bash
|
||||
# All services
|
||||
@@ -249,17 +246,17 @@ docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml logs -f ap
|
||||
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml logs --tail=100 api.core
|
||||
```
|
||||
|
||||
### Execute Commands in Container
|
||||
### Execute commands in container
|
||||
|
||||
```bash
|
||||
# Interactive shell
|
||||
docker exec -it dev-env-api-core bash
|
||||
|
||||
# Run command
|
||||
docker exec dev-env-sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'password' -C
|
||||
# Run command (replace <db-password> with the value of DB_PASSWORD from .env.dev)
|
||||
docker exec dev-env-sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P '<db-password>' -C
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
### Restart services
|
||||
|
||||
```bash
|
||||
# Restart all services
|
||||
@@ -272,7 +269,7 @@ docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml restart ap
|
||||
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml up -d --build api.core
|
||||
```
|
||||
|
||||
### Build Images
|
||||
### Build images
|
||||
|
||||
```bash
|
||||
# Build all images
|
||||
@@ -285,7 +282,7 @@ docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml build api.
|
||||
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml build --no-cache
|
||||
```
|
||||
|
||||
### Clean Up
|
||||
### Clean up
|
||||
|
||||
```bash
|
||||
# Stop and remove containers
|
||||
@@ -301,9 +298,9 @@ docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml down -v --
|
||||
docker system prune -af --volumes
|
||||
```
|
||||
|
||||
## Dockerfile Structure
|
||||
## Dockerfile structure
|
||||
|
||||
### Multi-Stage Build
|
||||
### Multi-stage build
|
||||
|
||||
```dockerfile
|
||||
# Stage 1: Build
|
||||
@@ -321,7 +318,7 @@ COPY --from=build /app/build .
|
||||
ENTRYPOINT ["dotnet", "Project.dll"]
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
## Additional resources
|
||||
|
||||
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
||||
- [.NET Docker Images](https://hub.docker.com/_/microsoft-dotnet)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Environment Variables
|
||||
# Environment variables
|
||||
|
||||
This document covers the active environment variables used by the current
|
||||
Biergarten stack.
|
||||
@@ -11,7 +11,7 @@ The application uses environment variables for:
|
||||
- **React Router website** - API base URL and session signing
|
||||
- **Docker containers** - environment-specific orchestration
|
||||
|
||||
## Configuration Patterns
|
||||
## Configuration patterns
|
||||
|
||||
### Backend (.NET API)
|
||||
|
||||
@@ -30,9 +30,9 @@ Environment-specific `.env` files loaded via `env_file:` in docker-compose.yaml:
|
||||
- `.env.test` - Testing
|
||||
- `.env.prod` - Production
|
||||
|
||||
## Backend Variables (.NET API)
|
||||
## Backend variables (.NET API)
|
||||
|
||||
### Database Connection
|
||||
### Database connection
|
||||
|
||||
**Option 1: Component-Based (Recommended for Docker)**
|
||||
|
||||
@@ -59,7 +59,7 @@ string is built from components.
|
||||
|
||||
**Implementation**: See `DefaultSqlConnectionFactory.cs`
|
||||
|
||||
### JWT Authentication Secrets (Backend)
|
||||
### JSON Web Token (JWT) authentication secrets (backend)
|
||||
|
||||
The backend uses separate secrets for different token types to enable
|
||||
independent key rotation and validation isolation.
|
||||
@@ -80,9 +80,9 @@ WEBSITE_BASE_URL=https://thebiergarten.app # Base URL for the website
|
||||
|
||||
**Security Requirements**:
|
||||
|
||||
- Each secret should be minimum 32 characters
|
||||
- Recommend 127+ characters for production
|
||||
- Generate using cryptographically secure random functions
|
||||
- Use at least 32 characters per secret
|
||||
- Use 127 or more characters in production
|
||||
- Generate secrets with a cryptographically secure random function
|
||||
- Never reuse secrets across token types or environments
|
||||
- Rotate secrets periodically in production
|
||||
|
||||
@@ -110,19 +110,20 @@ openssl rand -base64 127
|
||||
- **Handler**: Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler
|
||||
- **Validation**: Token signature, expiration, and malformed token checks
|
||||
|
||||
### Migration Control
|
||||
### Migration control
|
||||
|
||||
```bash
|
||||
CLEAR_DATABASE=true
|
||||
```
|
||||
|
||||
- **Required**: No
|
||||
- **Default**: false
|
||||
- **Effect**: If "true", drops and recreates database during migrations
|
||||
- **Usage**: Development and testing environments ONLY
|
||||
- **Warning**: NEVER use in production
|
||||
- **Default**: `false`
|
||||
- **Effect**: If set to `true`, drops and recreates the database during
|
||||
migrations
|
||||
- **Usage**: Development and testing environments only
|
||||
- **Warning**: Never use in production
|
||||
|
||||
### ASP.NET Core Configuration
|
||||
### ASP.NET Core configuration
|
||||
|
||||
```bash
|
||||
ASPNETCORE_ENVIRONMENT=Development # Development, Production, Staging
|
||||
@@ -130,7 +131,7 @@ ASPNETCORE_URLS=http://0.0.0.0:8080 # Binding address and port
|
||||
DOTNET_RUNNING_IN_CONTAINER=true # Flag for container execution
|
||||
```
|
||||
|
||||
## Frontend Variables (`web/frontend`)
|
||||
## Frontend variables (`web/frontend`)
|
||||
|
||||
The active website does not use the old Next.js/Prisma environment model. Its
|
||||
core runtime variables are:
|
||||
@@ -141,7 +142,7 @@ SESSION_SECRET=<generated-secret> # Cookie session signing secret
|
||||
NODE_ENV=development # Standard Node runtime mode
|
||||
```
|
||||
|
||||
### Frontend Variable Details
|
||||
### Frontend variable details
|
||||
|
||||
#### `API_BASE_URL`
|
||||
|
||||
@@ -163,7 +164,7 @@ NODE_ENV=development # Standard Node runtime mode
|
||||
- **Typical values**: `development`, `production`, `test`
|
||||
- **Purpose**: Controls secure cookie behavior and runtime mode
|
||||
|
||||
### SMTP Configuration (Backend)
|
||||
### SMTP configuration (backend)
|
||||
|
||||
Read by `Infrastructure.Email/SmtpEmailProvider.cs` for sending confirmation
|
||||
and account emails.
|
||||
@@ -183,11 +184,11 @@ SMTP_FROM_NAME=The Biergarten App # Optional, defaults to "The Biergarten
|
||||
- **Local dev**: point at the `mailpit` Docker service (SMTP on port 1025, web
|
||||
UI on http://localhost:8025)
|
||||
- **Production**: point at a real provider (SendGrid, Mailgun, Amazon SES,
|
||||
etc.)
|
||||
and so on)
|
||||
|
||||
## Docker-Specific Variables
|
||||
## Docker-specific variables
|
||||
|
||||
### SQL Server Container
|
||||
### SQL Server container
|
||||
|
||||
```bash
|
||||
SA_PASSWORD=YourStrong!Passw0rd # SQL Server SA password
|
||||
@@ -201,9 +202,9 @@ MSSQL_PID=Express # SQL Server edition (Express, Developer, Ente
|
||||
- Uppercase, lowercase, digits, and special characters
|
||||
- Maps to `DB_PASSWORD` for application containers
|
||||
|
||||
## Environment File Structure
|
||||
## Environment file structure
|
||||
|
||||
### Backend/Docker (`web/` Directory)
|
||||
### Backend/Docker (`web/` directory)
|
||||
|
||||
```
|
||||
web/.env.example # Template (tracked in Git)
|
||||
@@ -219,7 +220,7 @@ cp web/.env.example web/.env.dev
|
||||
# Edit web/.env.dev with your values
|
||||
```
|
||||
|
||||
## Legacy Frontend Variables
|
||||
## Legacy frontend variables
|
||||
|
||||
Variables for the archived Next.js frontend (`archive/next-js-web-app/`) have
|
||||
been removed from this active reference, since that app is retained for
|
||||
@@ -231,7 +232,7 @@ reference only and is not run as part of the active stack.
|
||||
- `web/docker-compose.test.yaml` → `web/.env.test`
|
||||
- `web/docker-compose.prod.yaml` → `web/.env.prod`
|
||||
|
||||
## Variable Reference Table
|
||||
## Variable reference table
|
||||
|
||||
| Variable | Backend | Frontend | Docker | Required | Notes |
|
||||
| ----------------------------- | :-----: | :------: | :----: | :------: | -------------------------- |
|
||||
@@ -268,7 +269,7 @@ reference only and is not run as part of the active stack.
|
||||
|
||||
## Validation
|
||||
|
||||
### Backend Validation
|
||||
### Backend validation
|
||||
|
||||
Variables are validated at startup:
|
||||
|
||||
@@ -279,7 +280,7 @@ Variables are validated at startup:
|
||||
"minimum 32 characters" guidance above is a recommendation, not an
|
||||
enforced check
|
||||
|
||||
### Frontend Validation
|
||||
### Frontend validation
|
||||
|
||||
The active website relies on runtime defaults for local development and the
|
||||
surrounding server environment in deployed environments.
|
||||
@@ -288,9 +289,9 @@ surrounding server environment in deployed environments.
|
||||
- `SESSION_SECRET` falls back to a development-only local secret
|
||||
- `NODE_ENV` controls secure cookie behavior
|
||||
|
||||
## Example Configuration Files
|
||||
## Example configuration files
|
||||
|
||||
### `.env.dev` (Backend/Docker)
|
||||
### `.env.dev` (backend/Docker)
|
||||
|
||||
```bash
|
||||
# Database
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Getting Started
|
||||
# Getting started
|
||||
|
||||
This guide covers local setup for the current Biergarten stack: the .NET backend
|
||||
in `web/backend` and the active React Router frontend in `web/frontend`.
|
||||
@@ -10,16 +10,16 @@ in `web/backend` and the active React Router frontend in `web/frontend`.
|
||||
- **Docker Desktop** or equivalent Docker Engine setup
|
||||
- **Java 8+** if you want to regenerate PlantUML diagrams
|
||||
|
||||
## Recommended Path: Docker for Backend, Node for Frontend
|
||||
## Recommended path: Docker for backend, Node for frontend
|
||||
|
||||
### 1. Clone the Repository
|
||||
### 1. Clone the repository
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
git clone https://github.com/aaronpo97/the-biergarten-app
|
||||
cd the-biergarten-app
|
||||
```
|
||||
|
||||
### 2. Configure Backend Environment Variables
|
||||
### 2. Configure backend environment variables
|
||||
|
||||
```bash
|
||||
cp web/.env.example web/.env.dev
|
||||
@@ -40,7 +40,7 @@ WEBSITE_BASE_URL=http://localhost:3000
|
||||
|
||||
See [Environment Variables](environment-variables.md) for the full list.
|
||||
|
||||
### 3. Start the Backend Stack
|
||||
### 3. Start the backend stack
|
||||
|
||||
```bash
|
||||
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml up -d
|
||||
@@ -54,7 +54,7 @@ Available endpoints:
|
||||
- Health Check: http://localhost:8080/health
|
||||
- Mailpit UI: http://localhost:8025
|
||||
|
||||
### 4. Start the Active Frontend
|
||||
### 4. Start the active frontend
|
||||
|
||||
```bash
|
||||
cd web/frontend
|
||||
@@ -69,7 +69,7 @@ Required frontend runtime variables for local work:
|
||||
- `API_BASE_URL` - Base URL for the .NET API
|
||||
- `SESSION_SECRET` - Cookie session signing secret for the website server
|
||||
|
||||
### 5. Optional: Run Storybook
|
||||
### 5. Optional: run Storybook
|
||||
|
||||
```bash
|
||||
cd web/frontend
|
||||
@@ -78,7 +78,7 @@ npm run storybook
|
||||
|
||||
Storybook runs at http://localhost:6006 by default.
|
||||
|
||||
## Useful Commands
|
||||
## Useful commands
|
||||
|
||||
### Backend
|
||||
|
||||
@@ -99,11 +99,11 @@ npm run test:storybook
|
||||
npm run test:storybook:playwright
|
||||
```
|
||||
|
||||
## Manual Backend Setup
|
||||
## Manual backend setup
|
||||
|
||||
If you do not want to use Docker, you can run the backend locally.
|
||||
|
||||
### 1. Set Environment Variables
|
||||
### 1. Set environment variables
|
||||
|
||||
```bash
|
||||
export DB_CONNECTION_STRING="Server=localhost,1433;Database=Biergarten;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;"
|
||||
@@ -113,7 +113,7 @@ export CONFIRMATION_TOKEN_SECRET="<generated>"
|
||||
export WEBSITE_BASE_URL="http://localhost:3000"
|
||||
```
|
||||
|
||||
### 2. Run Migrations and Seed
|
||||
### 2. Run migrations and seed
|
||||
|
||||
```bash
|
||||
cd web/backend
|
||||
@@ -127,12 +127,12 @@ dotnet run --project Database/Database.Seed/Database.Seed.csproj
|
||||
dotnet run --project API/API.Core/API.Core.csproj
|
||||
```
|
||||
|
||||
## Legacy Frontend Note
|
||||
## Legacy frontend note
|
||||
|
||||
The previous Next.js frontend lives in `archive/next-js-web-app/` for reference
|
||||
only and is not the active website.
|
||||
|
||||
## Next Steps
|
||||
## Next steps
|
||||
|
||||
- Review [Architecture](../architecture.md)
|
||||
- Run backend and frontend checks from [Testing](testing.md)
|
||||
|
||||
@@ -19,7 +19,7 @@ The project uses a multi-layered testing approach across backend and frontend:
|
||||
- **Storybook Playwright suite** - Browser checks against Storybook-rendered
|
||||
components
|
||||
|
||||
## Running Tests with Docker (Recommended)
|
||||
## Running tests with Docker (recommended)
|
||||
|
||||
The easiest way to run all tests is using Docker Compose, which sets up an
|
||||
isolated test environment:
|
||||
@@ -37,7 +37,7 @@ This command:
|
||||
5. Exports results to `./test-results/`
|
||||
6. Exits when tests complete
|
||||
|
||||
### View Test Results
|
||||
### View test results
|
||||
|
||||
```bash
|
||||
# List test result files
|
||||
@@ -51,18 +51,18 @@ cat test-results/Features.UserManagement.Tests.trx
|
||||
cat test-results/Features.Emails.Tests.trx
|
||||
```
|
||||
|
||||
### Clean Up
|
||||
### Clean up
|
||||
|
||||
```bash
|
||||
# Remove test containers and volumes
|
||||
docker compose --env-file web/.env.test -f web/docker-compose.test.yaml down -v
|
||||
```
|
||||
|
||||
## Running Tests Locally
|
||||
## Running tests locally
|
||||
|
||||
You can run individual test projects locally without Docker:
|
||||
|
||||
### Integration Tests (API.Specs)
|
||||
### Integration tests (API.Specs)
|
||||
|
||||
```bash
|
||||
cd web/backend
|
||||
@@ -75,7 +75,7 @@ dotnet test API/API.Specs/API.Specs.csproj
|
||||
- Database migrated and seeded
|
||||
- Environment variables set (DB connection, JWT secret)
|
||||
|
||||
### Feature Slice Unit Tests
|
||||
### Feature slice unit tests
|
||||
|
||||
Each feature slice has its own test project, covering its command/query
|
||||
handlers and repository:
|
||||
@@ -96,7 +96,7 @@ for proj in Features/*.Tests; do dotnet test "$proj"; done
|
||||
- No database required (handlers use Moq; repository tests use DbMocker to
|
||||
simulate SQL Server responses)
|
||||
|
||||
### Frontend Storybook Tests
|
||||
### Frontend Storybook tests
|
||||
|
||||
```bash
|
||||
cd web/frontend
|
||||
@@ -110,7 +110,7 @@ npm run test:storybook
|
||||
toasts, and the theme gallery
|
||||
- Runs in browser mode via Vitest and Storybook integration
|
||||
|
||||
### Frontend Playwright Storybook Tests
|
||||
### Frontend Playwright Storybook tests
|
||||
|
||||
```bash
|
||||
cd web/frontend
|
||||
@@ -125,9 +125,9 @@ npm run test:storybook:playwright
|
||||
- The command will start or reuse the Storybook server defined in
|
||||
`playwright.storybook.config.ts`
|
||||
|
||||
## Test Coverage
|
||||
## Test coverage
|
||||
|
||||
### Current Coverage
|
||||
### Current coverage
|
||||
|
||||
**Features.Auth.Tests**:
|
||||
|
||||
@@ -160,7 +160,7 @@ npm run test:storybook:playwright
|
||||
- Theme gallery rendering across Biergarten themes
|
||||
- Toast interactions and themed notification display
|
||||
|
||||
### Planned Coverage
|
||||
### Planned coverage
|
||||
|
||||
- [ ] Password reset functionality
|
||||
- [ ] Beer post operations
|
||||
@@ -168,7 +168,7 @@ npm run test:storybook:playwright
|
||||
- [ ] Image upload service
|
||||
- [ ] Frontend route integration coverage beyond Storybook stories
|
||||
|
||||
## Testing Frameworks & Tools
|
||||
## Testing frameworks and tools
|
||||
|
||||
### xUnit
|
||||
|
||||
@@ -200,9 +200,9 @@ npm run test:storybook:playwright
|
||||
- Simulates SQL Server responses
|
||||
- No real database required for unit tests
|
||||
|
||||
## Test Structure
|
||||
## Test structure
|
||||
|
||||
### API.Specs (Integration Tests)
|
||||
### API.Specs (integration tests)
|
||||
|
||||
```
|
||||
API.Specs/
|
||||
@@ -260,9 +260,9 @@ Each of the other three slices (`Features.Breweries.Tests`,
|
||||
`Features.UserManagement.Tests`, `Features.Emails.Tests`) follows the same
|
||||
shape: a `Commands/`/`Queries/` folder with one test file per handler.
|
||||
|
||||
## Writing Tests
|
||||
## Writing tests
|
||||
|
||||
### Unit Test Example (xUnit)
|
||||
### Unit test example (xUnit)
|
||||
|
||||
```csharp
|
||||
public class LoginHandlerTests
|
||||
@@ -287,7 +287,7 @@ public class LoginHandlerTests
|
||||
}
|
||||
```
|
||||
|
||||
### Integration Test Example (Reqnroll)
|
||||
### Integration test example (Reqnroll)
|
||||
|
||||
```gherkin
|
||||
Scenario: User login with valid credentials
|
||||
@@ -297,7 +297,7 @@ Scenario: User login with valid credentials
|
||||
And the response should contain a JWT token
|
||||
```
|
||||
|
||||
## Continuous Integration
|
||||
## Continuous integration
|
||||
|
||||
Tests run automatically in CI/CD pipelines using the test Docker Compose
|
||||
configuration:
|
||||
@@ -326,7 +326,7 @@ npm run test:storybook:playwright
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Tests Failing Due to Database Connection
|
||||
### Tests failing due to database connection
|
||||
|
||||
Ensure SQL Server is running and environment variables are set:
|
||||
|
||||
@@ -334,12 +334,12 @@ Ensure SQL Server is running and environment variables are set:
|
||||
docker compose --env-file web/.env.test -f web/docker-compose.test.yaml ps
|
||||
```
|
||||
|
||||
### Port Conflicts
|
||||
### Port conflicts
|
||||
|
||||
If port 1433 is in use, stop other SQL Server instances or modify the port in
|
||||
`docker-compose.test.yaml`.
|
||||
|
||||
### Stale Test Data
|
||||
### Stale test data
|
||||
|
||||
Clean up test database:
|
||||
|
||||
@@ -347,13 +347,13 @@ Clean up test database:
|
||||
docker compose --env-file web/.env.test -f web/docker-compose.test.yaml down -v
|
||||
```
|
||||
|
||||
### View Container Logs
|
||||
### View container logs
|
||||
|
||||
```bash
|
||||
docker compose --env-file web/.env.test -f web/docker-compose.test.yaml logs <service-name>
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
## Best practices
|
||||
|
||||
1. **Isolation**: Each test should be independent and not rely on other tests
|
||||
2. **Cleanup**: Use fixtures and dispose patterns for resource cleanup
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Token Validation Architecture
|
||||
# Token validation architecture
|
||||
|
||||
## Overview
|
||||
|
||||
The Core project validates JWTs across three token types:
|
||||
The Core project validates JSON Web Tokens (JWTs) across three token types:
|
||||
|
||||
- **Access Tokens**: Short-lived (1 hour) tokens for API authentication
|
||||
- **Refresh Tokens**: Long-lived (21 days) tokens for obtaining new access
|
||||
@@ -12,7 +12,7 @@ The Core project validates JWTs across three token types:
|
||||
|
||||
## Components
|
||||
|
||||
### Infrastructure Layer
|
||||
### Infrastructure layer
|
||||
|
||||
#### [ITokenInfrastructure](../../web/backend/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs)
|
||||
|
||||
@@ -30,7 +30,7 @@ Low-level JWT operations.
|
||||
- Algorithm: HS256 (HMAC-SHA256)
|
||||
- Validates token lifetime, signature, and well-formedness
|
||||
|
||||
### Features.Auth Slice
|
||||
### Features.Auth slice
|
||||
|
||||
#### [ITokenService](../../web/backend/Features/Features.Auth/Services/ITokenService.cs)
|
||||
|
||||
@@ -69,7 +69,7 @@ registered by the host (`API.Core/Program.cs`) since
|
||||
`JwtAuthenticationHandler` (host-level auth middleware) also depends on
|
||||
it directly.
|
||||
|
||||
### Integration Points
|
||||
### Integration points
|
||||
|
||||
#### [ConfirmUserHandler](../../web/backend/Features/Features.Auth/Commands/ConfirmUser/ConfirmUserHandler.cs)
|
||||
|
||||
@@ -112,9 +112,9 @@ it directly.
|
||||
- `POST /api/auth/confirm/resend?userId=...` - Resend the confirmation email
|
||||
- `POST /api/auth/refresh` - Refresh access token
|
||||
|
||||
## Validation Security
|
||||
## Validation security
|
||||
|
||||
### Token Secrets
|
||||
### Token secrets
|
||||
|
||||
Three independent secrets enable:
|
||||
|
||||
@@ -130,7 +130,7 @@ REFRESH_TOKEN_SECRET=... # Signs 21-day refresh tokens
|
||||
CONFIRMATION_TOKEN_SECRET=... # Signs 30-minute confirmation tokens
|
||||
```
|
||||
|
||||
### Validation Checks
|
||||
### Validation checks
|
||||
|
||||
Each token is validated for:
|
||||
|
||||
@@ -139,7 +139,7 @@ Each token is validated for:
|
||||
3. **Claims Presence** - Required claims (Sub, UniqueName) must be present
|
||||
4. **Claims Format** - UserId claim must be a valid GUID
|
||||
|
||||
### Error Handling
|
||||
### Error handling
|
||||
|
||||
Validation failures return HTTP 401 Unauthorized:
|
||||
|
||||
@@ -148,9 +148,9 @@ Validation failures return HTTP 401 Unauthorized:
|
||||
- Missing claims → "Invalid token"
|
||||
- Malformed claims → "Invalid token"
|
||||
|
||||
## Token Lifecycle
|
||||
## Token lifecycle
|
||||
|
||||
### Access Token Lifecycle
|
||||
### Access token lifecycle
|
||||
|
||||
1. **Generation**: During login (1-hour validity)
|
||||
2. **Usage**: Included in Authorization header on API requests
|
||||
@@ -158,16 +158,16 @@ Validation failures return HTTP 401 Unauthorized:
|
||||
4. **Expiration**: Token becomes invalid after 1 hour
|
||||
5. **Refresh**: Use refresh token to obtain new access token
|
||||
|
||||
### Refresh Token Lifecycle
|
||||
### Refresh token lifecycle
|
||||
|
||||
1. **Generation**: During login (21-day validity)
|
||||
2. **Storage**: Client-side (secure storage)
|
||||
3. **Usage**: Posted to `/api/auth/refresh` endpoint
|
||||
4. **Validation**: Validated by RefreshTokenService
|
||||
4. **Validation**: Validated by `ITokenService.RefreshTokenAsync()`
|
||||
5. **Rotation**: New refresh token issued on successful refresh
|
||||
6. **Expiration**: Token becomes invalid after 21 days
|
||||
|
||||
### Confirmation Token Lifecycle
|
||||
### Confirmation token lifecycle
|
||||
|
||||
1. **Generation**: During user registration (30-minute validity)
|
||||
2. **Delivery**: Emailed to user in confirmation link
|
||||
@@ -180,7 +180,7 @@ Validation failures return HTTP 401 Unauthorized:
|
||||
|
||||
All of the following live in `Features.Auth.Tests`.
|
||||
|
||||
### Unit Tests
|
||||
### Unit tests
|
||||
|
||||
**Services/TokenServiceValidationTests.cs**
|
||||
|
||||
@@ -210,7 +210,7 @@ All of the following live in `Features.Auth.Tests`.
|
||||
- Sends a fresh confirmation email when the user exists and is unverified
|
||||
- No-ops when the user doesn't exist or is already verified
|
||||
|
||||
### BDD Tests (Reqnroll)
|
||||
### BDD tests (Reqnroll)
|
||||
|
||||
**TokenRefresh.feature**
|
||||
|
||||
@@ -230,19 +230,19 @@ All of the following live in `Features.Auth.Tests`.
|
||||
- Invalid/expired access token rejection
|
||||
- Token type mismatch (refresh used as access token)
|
||||
|
||||
## Future Enhancements
|
||||
## Future enhancements
|
||||
|
||||
### Stretch Goals
|
||||
### Stretch goals
|
||||
|
||||
1. **Middleware for Access Token Validation**
|
||||
- Automatically validate access tokens on protected routes
|
||||
- Populate HttpContext.User from token claims
|
||||
- Return 401 for invalid/missing tokens
|
||||
|
||||
2. **Token Blacklisting**
|
||||
- Implement token revocation (e.g., on logout)
|
||||
- Store blacklisted tokens in cache/database
|
||||
- Check blacklist during validation
|
||||
2. **Token Denylisting**
|
||||
- Implement token revocation (for example, on logout)
|
||||
- Store denylisted tokens in cache/database
|
||||
- Check the denylist during validation
|
||||
|
||||
3. **Refresh Token Rotation Strategy**
|
||||
- Detect token reuse (replay attacks)
|
||||
|
||||
Reference in New Issue
Block a user