-
Work Log for SZ-20: Enable Basic Auth with JDBC-backed UserDetailsService
Timeline
- 2025-10-22: Issue created to address
401 Unauthorizederrors despite correct credentials. - 2025-10-23:
- Implemented
CustomUserDetailsServicebacked by Spring Data JPA. - Updated
BasicAuthSecurityConfigto use JDBC authentication andPasswordEncoder. - Added role-based access using
@PreAuthorizeand verified/api/usersrequiresROLE_ADMIN. - Verified login behavior via
curl -u admin@sztab.local:admin123on/api/users.
- Implemented
- 2025-10-24:
- Verified account creation and role assignment via POST
/api/users. - Diagnosed and resolved
TransientObjectExceptionby passing roleidin payload instead of justname. - Used
curlto list roles and confirm IDs. - Added
MarkdownViewControllerand/docs/index.htmlas static endpoint for testing public access. - Implemented and verified unit tests for
CustomUserDetailsService. - Merged branch
bugfix/sz20-basic-auth-yields-401towolnosc.
- Verified account creation and role assignment via POST
Technical Changes
- Created
CustomUserDetailsService.javato load users and roles from database. - Updated Spring Security config (
BasicAuthSecurityConfig.java) to:- Use
UserDetailsService - Encode passwords using
BCryptPasswordEncoder - Permit actuator endpoints and static docs without authentication
- Use
- Cleaned up
application.ymlto use properties appropriate for JDBC auth - Verified via
curlthat:- Basic Auth protects
/api/**endpoints - Role-based restrictions are enforced
- New users can be created with valid credentials
- Basic Auth protects
- Ensured new controller (
/docs/**) is public
Resolution
Basic Authentication is now enabled and functional using a JDBC-backed
UserDetailsService.
Test coverage added for the service, andcurlcalls verified successful user creation and protection of endpoints.
Branchbugfix/sz20-basic-auth-yields-401merged towolnosc.No version bump needed as this does not introduce any new externally visible features — internal correctness fix only.
- 2025-10-22: Issue created to address
-
Resolved.
Final implementation uses a JDBC-backed
UserDetailsServiceand fully verifies Basic Auth with curl-based user creation, login, and role retrieval.I originally estimated 2 hours but ended up spending ~7 hours, including time on a now-suspended UT approach. This helped clarify some Spring Security profile behavior, and I’ll factor this into future estimates.
Changes merged into
wolnosc. -
-
Engg-notes:
Hibernate Authentication Issue: Troubleshooting Recap
Problem
Despite having a user in the database (
admin@sztab.local), all REST API calls with basic auth were returning401 Unauthorized.Symptoms
curl -u admin@sztab.local:admin ...→ always failed with 401.- Spring logs showed:
BadCredentialsException: Bad credentials - DB query revealed the user password was stored in BCrypt form (
$2a$10$...), but the login password wasadmin(plaintext). - You also tried
{noop}password, but that didn’t work either.
Diagnosis
Spring Security uses
DaoAuthenticationProvider, which hashes the input password and compares it to the stored hash inuser.password.This is the correct behavior — but:
- You had manually inserted or updated users in the DB
- The password was either:
- Stored as
{noop}password(only works withNoOpPasswordEncoder) - Or out-of-sync with what Spring expected
- Or improperly hashed
- Stored as
So Spring couldn't match the credentials, and failed the authentication attempt.
Resolution
You generated a BCrypt hash for the password
adminusing Python:docker run --rm python:3-alpine \ sh -c "pip install bcrypt > /dev/null && python -c 'import bcrypt; print(bcrypt.hashpw(b\"admin\", bcrypt.gensalt()).decode())'"This output a bcrypt hash like:
$2b$12$4/Kl9lOOUO1kLODkBUcXzeaQqEBFynd2PVhZefbQH3vvHK39sUn.WThen you updated the
usertable directly:UPDATE "user" SET password = '$2b$12$4/Kl9lOOUO1kLODkBUcXzeaQqEBFynd2PVhZefbQH3vvHK39sUn.W' WHERE username = 'admin';And restarted the backend app:
docker restart sztab-backendThen confirmed it worked:
curl -u admin@sztab.local:admin http://localhost:8181/api/usersResponse: HTTP 200 + JSON user list
Takeaways
- Always use BCrypt-hashed passwords (never
{noop}unless explicitly supported) - Don’t insert plaintext passwords directly into the DB unless it's a test setup that uses
NoOpPasswordEncoder - If changing password manually → restart the backend
- Spring Security defaults to BCrypt, which is good (don’t override it casually)
Tip
To validate a password hash, you can also do it in a quick script:
import bcrypt password = b"admin" hashed = b"$2b$12$...." print(bcrypt.checkpw(password, hashed)) # True or False
| Type |
Bug
|
| Priority |
Normal
|
| Assignee | |
| Version |
1.0
|
| Sprints |
n/a
|
| Customer |
n/a
|
Problem
Sztab backend (v1.2) fails to authenticate the admin user via HTTP Basic Auth when running via Docker Compose, even though:
PasswordEncoderbean is correctly declared inBasicAuthSecurityConfig.Root Cause
The
JdbcUserDetailsManagerbean is not explicitly wired to thePasswordEncoder, so Spring Security may use the default (noop) encoder during authentication, leading to password mismatch.Logs
Workaround
No temporary workaround unless Spring autowires correctly via global context — behavior is unpredictable and environment-dependent.
Fix Plan
Inject the
PasswordEncoderintoJdbcUserDetailsManagerexplicitly inBasicAuthSecurityConfig:Impact
Only affects Basic Auth login for users stored in the DB (e.g.,
admin). All other functionality remains unaffected.