Spring Security Interview Questions

Commonly asked Spring Security interview questions with clear, practical answers.

A curated set of Spring Security interview questions, from the filter chain fundamentals through modern stateless authentication.

Q: How does the Spring Security filter chain work, at a high level?

Every incoming request passes through an ordered chain of servlet filters before it can reach a controller — each filter handles one concern (loading the security context, handling authentication, enforcing authorization rules). If any filter in the chain rejects the request (no valid credentials, or valid credentials without sufficient permission), the chain short-circuits and returns 401 Unauthorized or 403 Forbidden immediately, and the controller method never runs at all. This centralizes security logic in one consistently-applied place instead of duplicating checks inside every endpoint.

Q: What's the difference between stateless JWT authentication and traditional session-based authentication?

Session-based authentication stores authentication state server-side (a session, tied to a cookie the browser sends back automatically), which requires the server to remember who's logged in — and requires a shared session store to scale across multiple server instances. JWT authentication is stateless: after login, the server issues a signed token containing the user's identity, the client sends it back on every request (typically as an Authorization: Bearer header), and the server simply verifies the signature and reads the claims — no server-side session lookup at all, which scales horizontally with no shared state required. The trade-off is that a JWT can't be easily "logged out" server-side before it expires, since there's no session record to invalidate.

Q: Why should passwords always be hashed with something like BCryptPasswordEncoder instead of just compared as plain strings?

Storing or comparing plaintext passwords means anyone with read access to the database (or a database leak) immediately has every user's real password. BCryptPasswordEncoder produces a one-way hash with a random salt baked into the output, so identical passwords produce different hashes and the original password can't be recovered from the stored value. Authentication then uses passwordEncoder.matches(rawPassword, storedHash), which recomputes the hash the same way and compares — never decrypting or reversing anything.

Q: What's the difference between WebSecurityConfigurerAdapter and the current SecurityFilterChain approach?

WebSecurityConfigurerAdapter was the pre-Spring-Security-6 pattern: you subclassed it and overrode configure(HttpSecurity http) to declare rules. It was deprecated in Spring Security 5.7 and removed entirely in Spring Security 6 (the version that ships with Spring Boot 3), in favor of declaring a SecurityFilterChain as a plain @Bean method that configures and returns the built HttpSecurity chain. Functionally they express the same kind of rules; the newer approach favors composition (a @Bean) over inheritance, which is more consistent with how the rest of modern Spring configuration works.

Q: What's the difference between URL-level authorization and method-level security (@PreAuthorize)?

URL-level rules, configured in the SecurityFilterChain via authorizeHttpRequests, match against request paths and HTTP methods — coarse-grained, and evaluated before the request even reaches a controller. @PreAuthorize (enabled with @EnableMethodSecurity) is placed directly on a service or controller method and evaluates a SpEL expression that can reference the method's own parameters or the return value, which lets it express fine-grained, resource-specific rules — like "only the document's own owner or an admin can access it" — that a URL pattern alone has no way to express.

Q: How does OAuth2 "login with Google" actually work, at a high level?

The application redirects the user to Google's own login/consent screen instead of collecting a password itself; after the user approves, Google redirects back with an authorization code, which the application's server exchanges (server-to-server) for an access token and an ID token. The application then reads the user's basic profile (email, name) from the ID token or Google's userinfo endpoint and considers them authenticated — it never sees or handles the user's actual Google password at any point. Spring Security's .oauth2Login(...) configuration implements this entire authorization-code-flow exchange automatically once a provider is registered.

Q: What's the difference between CSRF and CORS, and why are they easy to confuse?

They're easy to confuse because both are browser-security mechanisms configured on the server, but they protect against opposite problems. CSRF protects against a forged request riding on a victim's own authenticated browser session — a malicious page tricking the browser into sending a request with the victim's real session cookie attached. CORS is what relaxes the browser's default same-origin restriction, explicitly allowing a legitimate frontend on a different origin to call your API at all. Disabling CSRF has nothing to do with configuring CORS, and vice versa — they solve unrelated problems that happen to both involve cross-origin requests.

Q: When is it actually safe to disable CSRF protection?

Only for genuinely stateless APIs that authenticate purely via a token sent in a header (like Authorization: Bearer <jwt>) with no session cookies involved at all — in that case there's no ambient, browser-attached credential a forged cross-origin request could exploit. For any application that relies on cookies or HttpSession for authentication — including traditional server-rendered form-based login — CSRF protection should stay enabled, since that's exactly the scenario it defends.

Q: What does the HSTS header protect against, and why can't a server just always redirect HTTP to HTTPS instead?

Strict-Transport-Security tells the browser to only ever contact a site over HTTPS for a configured duration, even if a later link, bookmark, or typed URL says http:// — the browser rewrites the request to HTTPS itself, before any network request is even sent. A server-side redirect from HTTP to HTTPS still requires that first plaintext HTTP request to reach the network, which is exactly the moment a man-in-the-middle attacker on the same network can intercept or strip it (a downgrade attack); HSTS closes that window by making the browser skip the plaintext request entirely on subsequent visits.