Spring Security — Interview Q&A Matrix
Parent stack: Spring Ecosystem Technology: Spring Security Levels: Senior Questions: 1
Each entry contains a Question, the Expected Depth, an Ideal Answer, and Red Flags.
Senior
Q1 — Securing an API with Spring Security and OAuth2
Question: How would you configure a Spring Boot 3 REST API as an OAuth2 resource server that validates JWTs and applies method-level authorization?
Expected Depth:
- Builds a
SecurityFilterChainand uses stateless session management. - Validates the JWT signature, issuer, audience, expiry, and not-before time.
- Maps trusted scope or role claims to Spring authorities.
- Enables method security and applies least-privilege rules.
- Distinguishes authentication failures (
401) from authorization failures (403). - Explains when CSRF protection can be disabled and why CORS is a separate concern.
- Covers JWKS rotation, short token lifetime, revocation needs, logging, and secret handling.
Ideal Answer:
- Add the OAuth2 resource-server dependency and configure the trusted issuer. Spring obtains the issuer metadata and JWKS, verifies the signature, and validates standard time claims:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://id.example.com/realms/payments- Build one explicit filter chain. Permit only public endpoints and require authentication everywhere else:
@Bean
SecurityFilterChain api(HttpSecurity http) throws Exception {
http
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.csrf(csrf -> csrf.disable())
.cors(Customizer.withDefaults())
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/actuator/health/liveness").permitAll()
.requestMatchers(HttpMethod.GET, "/payments/**")
.hasAuthority("SCOPE_payments:read")
.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults()));
return http.build();
}- Disabling CSRF is appropriate here only because authentication uses a bearer token in the
Authorizationheader and the browser does not attach it automatically. Keep CSRF protection for cookie or session authentication.STATELESSalone does not remove CSRF risk. - CORS controls which browser origins may call the API. It is not a replacement for authentication, authorization, or CSRF protection.
- Validate the expected audience as well as the issuer. A valid token for another API must not be accepted:
final class AudienceValidator implements OAuth2TokenValidator<Jwt> {
private final String requiredAudience;
AudienceValidator(String requiredAudience) {
this.requiredAudience = requiredAudience;
}
@Override
public OAuth2TokenValidationResult validate(Jwt jwt) {
if (jwt.getAudience().contains(requiredAudience)) {
return OAuth2TokenValidationResult.success();
}
OAuth2Error error = new OAuth2Error(
"invalid_token",
"The token audience is not accepted",
null);
return OAuth2TokenValidationResult.failure(error);
}
}
@Bean
JwtDecoder jwtDecoder(OAuth2ResourceServerProperties properties) {
NimbusJwtDecoder decoder = JwtDecoders.fromIssuerLocation(
properties.getJwt().getIssuerUri());
OAuth2TokenValidator<Jwt> issuer = JwtValidators.createDefaultWithIssuer(
properties.getJwt().getIssuerUri());
OAuth2TokenValidator<Jwt> audience = new AudienceValidator("payments-api");
decoder.setJwtValidator(
new DelegatingOAuth2TokenValidator<>(issuer, audience));
return decoder;
}- Spring maps
scopeorscpvalues to authorities with theSCOPE_prefix by default. If the identity provider uses a custom claim, configure aJwtAuthenticationConverterand accept values only from a trusted claim. - Enable method security and protect business operations close to the service layer:
@EnableMethodSecurity
@Configuration
class MethodSecurityConfig {}
@PreAuthorize("hasAuthority('SCOPE_payments:write')")
public void refund(String paymentId) {
paymentService.refund(paymentId);
}- Return
401 Unauthorizedwhen authentication is missing or invalid. Return403 Forbiddenwhen the token is valid but lacks permission. Use anAuthenticationEntryPointandAccessDeniedHandlerfor consistent problem responses, but do not expose token details. - Use HTTPS everywhere. Allow JWKS key rotation and monitor failures to refresh signing keys. Restrict accepted signing algorithms instead of trusting any algorithm in the token header.
- JWTs are difficult to revoke immediately. Use short access-token lifetimes, or use opaque-token introspection when the business requires central and immediate revocation.
- Never log access tokens, refresh tokens, signing keys, or full sensitive claims. Include only safe subject and correlation identifiers in audit logs.
Red Flags:
- Parses JWTs manually and trusts claims without signature validation.
- Validates the signature but not the issuer or audience.
- Accepts a role claim from any untrusted location in the token.
- Disables CSRF for cookie-based authentication.
- Says that CORS protects the API from unauthorized callers.
- Returns
403for an invalid or missing token, or401for a valid token with insufficient permission. - Exposes all actuator endpoints publicly.
- Uses long-lived JWTs with no revocation strategy.
- Logs bearer tokens or signing material.
- Adds endpoint rules but never secures sensitive service methods.
Scoring Rubric
| Level | Pass bar |
|---|---|
| Junior | Explains authentication, authorization, and bearer-token basics. |
| Senior | Validates tokens fully and applies least-privilege endpoint and method rules. |
| Architect | Defines identity, key rotation, revocation, audit, and failure-handling standards. |