Spaces:
Sleeping
Sleeping
Task User Service
Overview
Task User Service is the identity and profile microservice for the Task Management platform. It handles user onboarding, authentication, profile lookups, and directory queries. The service persists user data in MongoDB, issues JWTs for stateless security, discovers peers through Eureka, and publishes tracing data to Zipkin.
Tech Stack
- Spring Boot 3.2 (Java 17) with Gradle build
- Spring Security with JWT + Resilience4j circuit breakers
- MongoDB for user persistence via Spring Data
- Eureka client for service discovery
- Zipkin (Micrometer tracing bridge) for distributed tracing
Responsibilities
- Register new users, hashing credentials before persistence
- Authenticate users and issue signed JWT access tokens
- Resolve user profiles from bearer tokens
- Provide directory APIs for other microservices
- Expose health/readiness probes for orchestration
External Dependencies
| Service | Purpose | How to start locally |
|---|---|---|
| MongoDB | Primary datastore (user collection). |
docker run -d --name task-mongo -p 27017:27017 mongo:7.0 or install MongoDB 7.x manually. |
| Eureka | Service discovery (default http://localhost:8085/eureka). |
./gradlew bootRun from EurekaServerConfiguration or docker compose up eureka-server. |
| Zipkin | Distributed tracing (default http://localhost:9411). |
docker compose up zipkin or run Zipkin jar. |
A full environment (MongoDB, Zipkin, Eureka, and microservices) can be started from the repository root with
docker compose up -d mongodb zipkin eureka-server user-service.
Getting Started
- Prerequisites
- JDK 17+
- Docker (optional but recommended for MongoDB/Eureka/Zipkin)
- Gradle wrapper is bundled (
./gradlew)
- Environment configuration
Spring automatically reads the variables thanks tocd TaskUserService cp .env.example .env # update .env with secure values (especially TASK_JWT_SECRET)application.propertiesplaceholders. - Install & run dependencies
- MongoDB: ensure a database is available at
MONGODB_URI. Example using Docker:docker run -d --name task-mongo -p 27017:27017 mongo:7.0 - Zipkin & Eureka: start locally or via Compose. From repo root:
docker compose up -d zipkin eureka-server
- MongoDB: ensure a database is available at
- Run the service locally
The API listens on./gradlew clean bootRunhttp://localhost:${SERVER_PORT:-8081}. Make sure.envis loaded in your shell or an IDE run configuration. - Run the service with Docker Compose
Compose automatically wires environment variables declared for the service profile.docker compose up -d user-service - Execute tests
./gradlew test
Environment Variables
The service is fully configurable via environment variables; see .env.example for a ready-to-copy template.
| Variable | Default | Description |
|---|---|---|
SERVER_PORT |
8081 |
HTTP port exposed by the service. |
MONGODB_URI |
mongodb://localhost:27017/userData |
MongoDB connection string. |
EUREKA_SERVER_URI |
http://localhost:8085/eureka |
Eureka discovery endpoint. |
ZIPKIN_BASE_URL |
http://localhost:9411 |
Zipkin server URL. |
ZIPKIN_SAMPLER_PROBABILITY |
1.0 |
Sampling ratio for tracing. |
TASK_JWT_SECRET |
required (default placeholder) | Secret used to sign JWTs (must be β₯ 32 chars). |
TASK_JWT_ACCESS_TOKEN_TTL_MINUTES |
1440 |
JWT access token lifetime in minutes. |
TASK_ALLOWED_ORIGINS |
http://localhost:3000 |
Comma-separated list of allowed CORS origins. |
TASK_ALLOWED_HEADERS |
* |
Allowed CORS headers. |
TASK_ALLOWED_METHODS |
GET,POST,PUT,PATCH,DELETE,OPTIONS |
Allowed CORS methods. |
TASK_ALLOW_CREDENTIALS |
true |
Whether cross-site credentials are allowed. |
TASK_CORS_MAX_AGE |
3600 |
CORS cache duration in seconds. |
LOG_LEVEL_ROOT |
INFO |
Default logging level. |
LOG_LEVEL_APP |
INFO |
Package-specific logging level. |
API Surface
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/auth/signup |
β | Register a new user and auto-sign in (returns JWT). |
POST |
/auth/signin |
β | Authenticate with email/password and receive a JWT. |
GET |
/api/users/profile |
β | Retrieve the profile of the caller based on JWT. |
GET |
/api/users/{userId} |
β | Fetch a specific user by id. |
GET |
/api/users |
β | List all users (sensitive fields removed). |
GET |
/api/users/health |
β | Lightweight readiness check. |
GET |
/actuator/health |
β | Spring Boot actuator health endpoint. |
Example signup request:
curl -X POST http://localhost:8081/auth/signup \
-H 'Content-Type: application/json' \
-d '{
"fullName": "Ada Lovelace",
"email": "ada@example.com",
"password": "Sup3rSecret!",
"mobile": "1234567890"
}'
Use the jwt field returned from signup/signin as Authorization: Bearer <token> for protected routes.
Error Handling & Resilience
- Centralised
GlobalExceptionHandlerconverts validation, authentication, and domain errors into consistentApiResponsepayloads. - Sensitive fields (password hashes) are removed from outbound responses via dedicated
UserResponseDTOs. - Resilience4j circuit breakers wrap user lookups and authentication flows; fallbacks surface
503 Service Unavailableresponses when tripped. - JWT validation happens in a single filter using configurable secrets and token TTLs; invalid or missing tokens no longer poison the security context.
Troubleshooting
- Mongo connection refused: ensure MongoDB is running and
MONGODB_URImatches credentials/host. With Docker, verifydocker psshowstask-mongohealthy. - JWT secret errors: the application now validates that
TASK_JWT_SECRETis at least 32 characters. Update.envbefore starting the service. - 401 after login: confirm the
Authorizationheader uses theBearerprefix and the token has not expired (see configured TTL). - Eureka/Zipkin unavailable: startup succeeds without them, but resilience metrics degrade. Adjust
.envor bring the services up via Compose. - CORS failures: update
TASK_ALLOWED_ORIGINSwith the exact origin(s) of the frontend (comma separated). - Port conflicts: change
SERVER_PORTin your.envand restart (./gradlew bootRun).
Recent Fixes & Refactors
- Replaced hard-coded JWT constants with validated configuration properties and injected
JwtProviderbean. - Added stateless security filter chain with configurable CORS and a single
JwtTokenValidatorinstance. - Introduced
UserResponseDTOs to strip sensitive data and harmonised HTTP status codes (200/503 instead of 202/500). - Implemented global exception handling and structured logging across controllers and services.
- Parameterised configuration through environment variables, shipped
.env.example, and refreshed documentation.