Test your Spring Security knowledge with 20 interview questions covering authentication, authorization, JWT, OAuth2, CORS, CSRF, SecurityFilterChain, and role-based access control.
Below are all 20 questions covered in this quiz, grouped by topic. Each question includes the correct answer and a detailed explanation to help you prepare for your next interview.
What is the difference between authentication and authorization in Spring Security?
Authentication verifies the identity of a user; authorization determines what resources the authenticated user is allowed to access
Authentication is the process of verifying a user's identity (e.g., via username/password, JWT, or OAuth2). Authorization happens after authentication and determines what the verified user is permitted to do. In Spring Security, authentication is handled by AuthenticationManager and authorization by AccessDecisionManager or AuthorizationManager.
What is the purpose of UserDetailsService in Spring Security?
It is a core interface used to load user-specific data during authentication, typically by looking up a user from a database
UserDetailsService has a single method, loadUserByUsername(String username), which returns a UserDetails object containing the username, password, and granted authorities. Spring Security calls this during authentication to retrieve the user's stored credentials and roles. You typically implement it to query your database. The returned UserDetails is then compared against the credentials the user provided.
What is the role of SecurityFilterChain in Spring Security, and how do you configure it in a modern Spring Boot application?
It is a bean that defines a chain of security filters applied to HTTP requests, configured by returning it from a @Bean method in a @Configuration class
Since Spring Security 5.7+, the recommended approach is to define a SecurityFilterChain bean instead of extending WebSecurityConfigurerAdapter (which is deprecated). You create a @Configuration class with a @Bean method that accepts HttpSecurity, configures rules (e.g., authorizeHttpRequests, csrf, cors, sessionManagement), and returns http.build(). Multiple SecurityFilterChain beans can coexist for different URL patterns.
Given the following Spring Security configuration, which statement is correct?
```java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.build();
}
```The /api/public/ endpoints are open, /api/admin/ requires ADMIN role, and all other endpoints require authentication via HTTP Basic
The rules are evaluated in order. requestMatchers("/api/public/**").permitAll() allows unauthenticated access to public endpoints. requestMatchers("/api/admin/**").hasRole("ADMIN") restricts admin endpoints to users with the ADMIN role. anyRequest().authenticated() requires authentication for everything else. httpBasic(Customizer.withDefaults()) enables HTTP Basic authentication as the mechanism.
How does Spring Security's filter chain ordering work, and why does the order of filters matter?
Spring Security defines a specific filter ordering (e.g., CORS, CSRF, authentication, authorization) so that each filter can rely on the work of previous filters in the chain
Spring Security's filter chain follows a strict order. Key filters include: CorsFilter (handles CORS preflight), CsrfFilter (validates CSRF tokens), UsernamePasswordAuthenticationFilter (processes form login), BearerTokenAuthenticationFilter (processes JWT/OAuth2 tokens), ExceptionTranslationFilter (converts security exceptions to HTTP responses), and AuthorizationFilter (enforces access rules). Each filter depends on earlier filters having completed their work. For example, the authorization filter needs the authentication to be set by an earlier authentication filter.
What happens when you have multiple SecurityFilterChain beans? How does Spring Security decide which one to apply?
```java
@Bean
@Order(1)
public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
return http
.securityMatcher("/api/**")
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults())
.build();
}
@Bean
@Order(2)
public SecurityFilterChain webFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.build();
}
```Spring Security evaluates chains by @Order; the first chain whose securityMatcher matches the request is used exclusively
When multiple SecurityFilterChain beans exist, Spring Security evaluates them in @Order (lowest value first). For each request, it picks the first chain whose securityMatcher matches. In this example, requests to /api/** are handled by the first chain (HTTP Basic auth). All other requests fall through to the second chain (form login). Only one chain is used per request. This pattern is common when an application serves both a REST API and a web UI with different authentication mechanisms.
Why does Spring Security recommend BCrypt for password hashing, and how do you configure it?
BCrypt is an adaptive hashing function with a configurable work factor that makes brute-force attacks expensive; you configure it by defining a BCryptPasswordEncoder bean
BCrypt is a deliberately slow, adaptive hashing function. Its work factor (strength) can be increased over time as hardware improves, making brute-force attacks progressively harder. Unlike MD5 or SHA-256, BCrypt includes a built-in salt. Configure it by declaring a @Bean of type PasswordEncoder that returns new BCryptPasswordEncoder(). Spring Security's DelegatingPasswordEncoder also supports BCrypt as the default.
What are the three parts of a JSON Web Token (JWT)?
Header, payload, and signature
A JWT consists of three Base64URL-encoded parts separated by dots: the Header (specifies the signing algorithm, e.g., HS256 or RS256, and token type), the Payload (contains claims such as sub, iat, exp, and custom claims like roles), and the Signature (created by signing the encoded header and payload with a secret or private key). The signature ensures the token has not been tampered with.
How do you implement a custom JWT authentication filter in Spring Security?
Create a filter extending OncePerRequestFilter that extracts the token from the Authorization header, validates it, builds an Authentication object, and sets it in the SecurityContextHolder
A typical JWT filter extends OncePerRequestFilter and overrides doFilterInternal(). It reads the Authorization header, strips the "Bearer " prefix, validates the token (checking signature and expiration), extracts the username and authorities, creates a UsernamePasswordAuthenticationToken, and places it in SecurityContextHolder.getContext().setAuthentication(). The filter is registered in the SecurityFilterChain using addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class).
What is wrong with this JWT validation logic?
```java
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
```It catches all exceptions generically, hiding specific failure reasons (expired, malformed, invalid signature) that should be logged or handled differently for security monitoring
While this code does validate the JWT, catching a generic Exception swallows important security information. The JJWT library throws specific exceptions: ExpiredJwtException (token expired), MalformedJwtException (invalid format), SignatureException (tampered token), and UnsupportedJwtException. Each should be caught separately so you can log the specific failure reason, which is critical for detecting attacks. An expired token is normal; an invalid signature could indicate a security breach.
In OAuth2, what is the Authorization Code flow, and why is it preferred for server-side applications?
The user authenticates with the authorization server, which returns an authorization code to the client; the client then exchanges the code for an access token via a back-channel request
The Authorization Code flow is the most secure standard OAuth2 flow for server-side apps. The user is redirected to the authorization server to log in. After consent, the server redirects back with a short-lived authorization code. The client application exchanges this code for an access token via a server-to-server (back-channel) request, keeping the token out of the browser. Spring Security supports this via spring-boot-starter-oauth2-client with minimal configuration.
How do you configure Spring Boot as an OAuth2 Resource Server that validates JWT tokens?
Add spring-boot-starter-oauth2-resource-server, set spring.security.oauth2.resourceserver.jwt.issuer-uri in application.yml, and Spring Security automatically validates incoming JWTs
Spring Boot's OAuth2 Resource Server support (spring-boot-starter-oauth2-resource-server) provides automatic JWT validation. Set spring.security.oauth2.resourceserver.jwt.issuer-uri to your authorization server's issuer URL (e.g., Keycloak, Auth0). Spring Security will fetch the JWKS (JSON Web Key Set) from the issuer's well-known endpoint, validate the token's signature, expiration, and issuer claim automatically. In the SecurityFilterChain, enable it with .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())).
What does the following CORS configuration do?
```java
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", config);
return source;
}
```It allows cross-origin requests to /api/** only from https://example.com, with specific methods and headers, and permits credentials (cookies/auth headers)
This configuration creates a CorsConfigurationSource bean that Spring Security's CorsFilter uses. It restricts cross-origin requests to /api/** endpoints from only https://example.com, allowing GET, POST, PUT, and DELETE methods with Authorization and Content-Type headers. setAllowCredentials(true) means the browser will send cookies and authorization headers with cross-origin requests. This is activated in SecurityFilterChain via .cors(Customizer.withDefaults()).
What is CSRF protection in Spring Security, and when is it safe to disable it?
CSRF protection prevents forged requests from malicious sites by requiring a token; it is safe to disable for stateless REST APIs that use token-based authentication (e.g., JWT) instead of cookies
Cross-Site Request Forgery (CSRF) attacks trick a user's browser into making unwanted requests to a site where they are authenticated via cookies. Spring Security's CSRF protection requires a unique token in state-changing requests (POST, PUT, DELETE). For stateless REST APIs that authenticate via JWT in the Authorization header (not cookies), CSRF is not a risk because the browser does not automatically attach the token. In that case, it is common to disable CSRF via .csrf(csrf -> csrf.disable()).
What does the @PreAuthorize annotation do in the following code?
```java
@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
public UserProfile getProfile(Long userId) {
return userRepository.findById(userId).orElseThrow();
}
```It checks before method execution that the caller has ADMIN role OR the requested userId matches the authenticated user's ID
@PreAuthorize evaluates a SpEL expression before the method executes. In this example, it allows access if the user has the ADMIN role OR if the userId parameter matches the authenticated principal's ID. This is a common pattern for "admins can see anyone's profile, users can only see their own." Method-level security must be enabled with @EnableMethodSecurity on a configuration class.
What is the difference between @Secured and @PreAuthorize in Spring Security?
@Secured supports only role-based checks with simple strings, while @PreAuthorize supports SpEL expressions for complex authorization logic including method parameters
@Secured is a simpler annotation that accepts an array of role names (e.g., @Secured({"ROLE_ADMIN", "ROLE_USER"})). It does not support SpEL. @PreAuthorize uses Spring Expression Language and can reference method parameters, the authentication object, and call custom methods (e.g., @PreAuthorize("hasRole('ADMIN') and #entity.ownerId == authentication.principal.id")). @PreAuthorize is more flexible and is the preferred approach in modern Spring Security applications.
What is the difference between hasRole('ADMIN') and hasAuthority('ROLE_ADMIN') in Spring Security?
They are functionally equivalent; hasRole('ADMIN') automatically prepends the 'ROLE_' prefix, while hasAuthority('ROLE_ADMIN') checks the full authority string
In Spring Security, roles are authorities with a 'ROLE_' prefix. hasRole('ADMIN') is a convenience method that automatically prepends 'ROLE_' and checks for the authority 'ROLE_ADMIN'. hasAuthority('ROLE_ADMIN') checks the exact authority string. They produce the same result. Use hasAuthority when you have fine-grained permissions (e.g., 'READ_USERS', 'WRITE_USERS') that do not follow the ROLE_ convention.
You need to implement role-based access where:
- /api/public/** is open to everyone
- /api/user/** requires USER or ADMIN role
- /api/admin/** requires ADMIN role
- A custom JWT filter handles authentication
Which SecurityFilterChain configuration is correct?``java
http.csrf(csrf -> csrf.disable())
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
``
The correct configuration disables CSRF (appropriate for a stateless JWT API), sets session policy to STATELESS, defines authorization rules in the right order (most specific first), and registers the JWT filter before the default UsernamePasswordAuthenticationFilter. Option C is missing CSRF/session config and the JWT filter. Option D is wrong because anyRequest().authenticated() placed first would match all requests before the permitAll rule is reached. Order matters in authorization rules.
How do you configure session management in Spring Security to make an application stateless?
Configure .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) in the SecurityFilterChain
For REST APIs using token-based authentication (JWT), you should set the session creation policy to STATELESS. This tells Spring Security not to create or use HTTP sessions. Without this, Spring Security defaults to creating sessions and storing the SecurityContext in the session, which is unnecessary overhead for JWT-based APIs and can cause unexpected behavior. This is configured in the SecurityFilterChain builder: .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).
Which security headers does Spring Security add by default, and what do they protect against?
It adds headers like X-Content-Type-Options (prevents MIME sniffing), X-Frame-Options (prevents clickjacking), Cache-Control (prevents caching of sensitive data), and X-XSS-Protection
Spring Security automatically adds several protective response headers. X-Content-Type-Options: nosniff prevents browsers from MIME-type sniffing. X-Frame-Options: DENY prevents the page from being embedded in iframes (clickjacking). Cache-Control: no-cache, no-store prevents sensitive data from being cached. Strict-Transport-Security (HSTS) enforces HTTPS. These defaults follow security best practices and can be customized via .headers() in the SecurityFilterChain configuration.
Take the interactive quiz and get your score with a personalized topic breakdown.
Start the Quiz20 questions · 30 min
Java20 questions · 30 min
Java20 questions · 30 min
Java20 questions · 30 min
Java20 questions · 30 min
Java20 questions · 30 min
Spring Boot20 questions · 30 min
Spring Boot20 questions · 30 min
Spring Boot20 questions · 30 min
Spring Boot20 questions · 30 min
Spring Boot20 questions · 30 min
DevOps20 questions · 30 min
Join thousands of developers mastering in-demand skills with Amigoscode. Try it free today.