UserDetailsService and UserDetails — Custom Implementation
Fast recall
Quick revision
Core answer
loadUserByUsername(), then verifies the submitted password with PasswordEncoder. Map status flags to real columns (locked, enabled, password-expired) so flipping a flag in the DB instantly blocks login without code changes.Whether the candidate can wire Spring Security to a real user database — the most common integration task.
Returning a plain Spring Security User object without implementing account expiry or lock flags, causing confusing authentication failures.
Discuss caching UserDetails to avoid database hits on every request, UserDetailsPasswordService for password upgrade, and the difference between isEnabled() and isAccountNonLocked().
Interview-ready guide
Interview answer
Bridge contract
UserDetailsServicehas one method:loadUserByUsername(String)returningUserDetails- Connects Spring Security to any user store (DB, LDAP, REST)
DaoAuthenticationProvidercalls it during authentication, then usesPasswordEncoder.matches
Implementation pattern
- Implement
UserDetailsServiceas a@Servicebean — Spring Boot auto-wires it - Implement
UserDetailson a wrapper around yourAppUserentity - Map
getAuthorities()from your roles, prefixing withROLE_
Status flag pitfalls
- Four booleans: enabled, account-non-expired, account-non-locked, credentials-non-expired
- Each maps to a different exception (Disabled, Expired, Locked, CredentialsExpired)
- All converted to generic
"Bad credentials"to prevent enumeration - Map them to real columns so admin actions take effect immediately
Performance
- Per-request DB hit only matters with session-based + reload-every-request pattern
- Cache with
@Cacheable, TTL 1-5 min, evict on user updates - For Spring Session/Redis, principal is in the session — no per-request lookup
Algorithm migration
- Implement
UserDetailsPasswordService.updatePassword DelegatingPasswordEncoderdetects old algorithm and re-hashes with new one on login- Persist the new hash — lazy migration with zero user impact
Security
- Same error message for unknown user and wrong password
- Never log password or full principal
- Use opaque session IDs; rotate on login (prevents fixation)
UserDetailsService and UserDetails — Custom Implementation
Direct Answer
UserDetailsService is a single-method interface that loads user data by username; Spring Security calls it during authentication. UserDetails is an interface describing the loaded user — credentials, four account-status flags, and granted authorities. You implement both to connect Spring Security to your own database or user store, replacing the default in-memory user management. DaoAuthenticationProvider invokes loadUserByUsername(), then verifies the submitted password with PasswordEncoder. Map status flags to real columns (locked, enabled, password-expired) so flipping a flag in the DB instantly blocks login without code changes.
Common Mistakes & Pitfalls
Returning a plain Spring Security User object without implementing account expiry or lock flags, causing confusing authentication failures.
Check your understanding
Answer these without looking back at the article.
- What exception does Spring Security throw when isEnabled() returns false, and how would you handle it in a custom AuthenticationFailureHandler?
- How would you cache UserDetails to avoid a database query on every authenticated request?
- What is UserDetailsPasswordService and when would you use it?
- How do you support two different UserDetailsService implementations (admin vs customer)?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.