|
1 | 1 | # Spring Boot Security & Observability Lab |
2 | 2 |
|
3 | | -A hands-on lab demonstrating the architectural evolution of a Spring Boot application from a secure monolith to a fully observable, distributed system using modern DevSecOps practices. |
| 3 | +This repository is a hands-on lab designed to demonstrate the architectural evolution of a modern Java application. We |
| 4 | +will build a system from the ground up, starting with a secure monolith and progressively refactoring it into a fully |
| 5 | +observable, distributed system using cloud-native best practices. |
4 | 6 |
|
5 | | -*This README is a placeholder and will be fully populated as the project evolves.* |
| 7 | +--- |
| 8 | + |
| 9 | +## Lab Progress: Phase 1 - The Standalone Secure Monolith |
| 10 | + |
| 11 | +The `main` branch currently represents the completed state of **Phase 1**. |
| 12 | + |
| 13 | +### Objective |
| 14 | + |
| 15 | +The goal of this phase is to establish a robust security baseline for a standalone REST API. The service is responsible |
| 16 | +for both authenticating users and issuing its own JSON Web Tokens (JWTs) without any external identity providers. |
| 17 | + |
| 18 | +### Key Concepts Demonstrated |
| 19 | + |
| 20 | +* **Self-Contained JWT Authentication:** The service acts as its own Authorization Server. |
| 21 | +* **Credential Validation:** Correctly delegating username/password validation to Spring Security's |
| 22 | + `AuthenticationManager`. |
| 23 | +* **Token Generation:** Using the `io.jsonwebtoken` (`jjwt`) library to create signed, expiring JWTs. |
| 24 | +* **Custom Token Validation:** Implementing a custom `OncePerRequestFilter` to intercept requests, validate the Bearer |
| 25 | + token, and populate Spring's `SecurityContext`. |
| 26 | +* **Stateless API Design:** Ensuring the application is fully stateless, a prerequisite for modern scalable services. |
| 27 | + |
| 28 | +### Architecture Overview |
| 29 | + |
| 30 | +The architecture for Phase 1 is a single Spring Boot application. The security logic is composed of three main |
| 31 | +components: |
| 32 | + |
| 33 | +1. **[SecurityConfig](resource-server/src/main/java/com/apenlor/lab/resourceserver/config/SecurityConfig.java):** This |
| 34 | + is the core configuration class. It defines the `AuthenticationManager` for validating credentials, sets up the |
| 35 | + `UserDetailsService` (using an in-memory store for this phase), and configures the main `SecurityFilterChain`. |
| 36 | +2. **[TokenService](resource-server/src/main/java/com/apenlor/lab/resourceserver/service/TokenService.java):** A |
| 37 | + dedicated service that encapsulates all logic for creating and parsing JWTs using the `jjwt` library and our secret |
| 38 | + key. |
| 39 | +3. **[JwtAuthenticationFilter](resource-server/src/main/java/com/apenlor/lab/resourceserver/config/JwtAuthenticationFilter.java):** |
| 40 | + A custom filter that is added to the security chain. On every request to a protected endpoint, this filter |
| 41 | + extracts the `Bearer` token, uses the `TokenService` to validate it, and establishes the user's identity for the |
| 42 | + duration of the request. |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +## Local Development & Quick Start |
| 47 | + |
| 48 | +The only prerequisite is a Java 21 JDK. |
| 49 | + |
| 50 | +1. **Build the application:** |
| 51 | + ```bash |
| 52 | + ./mvnw clean install |
| 53 | + ``` |
| 54 | +2. **Run the application:** |
| 55 | + ```bash |
| 56 | + ./mvnw -pl resource-server spring-boot:run |
| 57 | + ``` |
| 58 | + The application will start on `http://localhost:8081`. |
| 59 | + |
| 60 | +--- |
| 61 | + |
| 62 | +## API Usage Examples (Phase 1) |
| 63 | + |
| 64 | +*(Requires a command-line JSON processor like `jq` to easily extract the token.)* |
| 65 | + |
| 66 | +#### 1. Authenticate and Get a Token |
| 67 | + |
| 68 | +Send the hardcoded credentials to the `/auth/login` endpoint to receive a JWT. |
| 69 | + |
| 70 | +```bash |
| 71 | + TOKEN=$(curl -s -X POST http://localhost:8081/auth/login \ |
| 72 | + -H "Content-Type: application/json" \ |
| 73 | + -d '{"username":"user", "password":"password"}' | jq -r .jwtToken) |
| 74 | + |
| 75 | + echo "Acquired Token: $TOKEN" |
| 76 | +``` |
| 77 | + |
| 78 | +#### 2. Access the Public Endpoint |
| 79 | + |
| 80 | +This endpoint requires no token and should always succeed. |
| 81 | + |
| 82 | +```bash |
| 83 | + curl http://localhost:8081/api/public/info |
| 84 | +``` |
| 85 | + |
| 86 | +#### 3. Access the Secure Endpoint (with Token) |
| 87 | + |
| 88 | +Use the acquired token in the `Authorization` header to access the protected resource. |
| 89 | + |
| 90 | +```bash |
| 91 | + curl http://localhost:8081/api/secure/data -H "Authorization: Bearer $TOKEN" |
| 92 | +``` |
| 93 | + |
| 94 | +#### 4. Access the Secure Endpoint (without Token) |
| 95 | + |
| 96 | +This request will fail with a `401 Unauthorized` error, as handled by our security configuration. |
| 97 | + |
| 98 | +```bash |
| 99 | + curl -i http://localhost:8081/api/secure/data |
| 100 | +``` |
0 commit comments