Today I started building a Smart Reconciliation and Audit System , a real enterprise grade project that companies use to match uploaded financial transactions against system records and flag mismatches.
Just me, IntelliJ Idea, and a lot of errors.
What I built today,
- Integrated JWT-based authentication to generate secure tokens for users,
- Implemented role-based access control (Admin, Analyst, Viewer).
- Configured Spring Security for stateless session management and endpoint protection.
- Designed structured API request & response handling for clean communication between frontend and backend.
- Secured user data by encrypting passwords using BCrypt.
- Built logic to validate users and generate tokens dynamically during login.
- Implemented request filtering to validate JWT tokens on every API call.
- Seeded the database with default users (Admin, Analyst, Viewer) for testing and initial system setup.
Things I understood today:
- When User sends username & password to login endpoint.
- Server creates a UsernamePasswordAuthenticationToken using the credentials.
- This token is passed to AuthenticationManager
- AuthenticationManager internally calls UserDetailsService.loadUserByUsername() to fetches user data from database.
- Password is validated using PasswordEncoder (BCrypt).
- If valid → authentication is successful, If invalid → exception is thrown.
- Controller generates JWT token. It is sent back to the client.
For Subsequent Requests:
- Client sends request with the token.
- JWT Filter intercepts the request before controller.
- Filter extracts token and validates it using JwtUtil.
- If valid, Extract username, Load user again using UserDetailsService,Set authentication in SecurityContextHolder.
- Request proceeds to controller.
Mistakes I made
Mistake 1 — wrong JWT algorithm
Used SignatureAlgorithm.ES256 which requires an elliptic curve key pair — completely different setup. Should be HS256 which works with a simple string secret.
Mistake 2 — seeded users without encoding passwords
When creating default users in DataInitializer, I saved plain text passwords. Then login failed because passwordEncoder.matches() expects BCrypt hash, not plain text.
Tested in Postman:
Role based authentication:
Used Api Response for ensuring same structure: