Skip to main content

Quiz: Spring Security

Test your knowledge on Spring Security, JWT, and OAuth2.

30 questions - Click on each question to reveal the answer.


Questions 1-10: Security Fundamentals​

Question 1: Which dependency to add for Spring Security?

Answer:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

By default, all routes are protected.


Question 2: What happens when you add Spring Security without configuration?

Answer:

  • All routes require authentication
  • A login form is displayed
  • A user is created with a generated password (displayed in logs)
  • CSRF is enabled

Question 3: How to configure security in Spring Boot 3?

Answer:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());

return http.build();
}
}

Question 4: What is the difference between authenticated() and permitAll()?

Answer:

  • permitAll(): accessible without authentication
  • authenticated(): requires an authenticated user
  • hasRole("X"): requires role X
  • hasAuthority("X"): requires authority X

Question 5: How to define in-memory users?

Answer:

@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("password"))
.roles("USER")
.build();

UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin"))
.roles("ADMIN")
.build();

return new InMemoryUserDetailsManager(user, admin);
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Question 6: How to implement UserDetailsService with a database?

Answer:

@Service
public class CustomUserDetailsService implements UserDetailsService {

private final UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));

return org.springframework.security.core.userdetails.User.builder()
.username(user.getEmail())
.password(user.getPassword())
.roles(user.getRole().name())
.build();
}
}

Question 7: Why encode passwords?

Answer:

  • Security: passwords unreadable if DB compromised
  • BCrypt: generates a different hash each time (salt integrated)
  • Requirement: Spring Security refuses plain text passwords
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Question 8: What is the difference between Role and Authority?

Answer:

  • Role: automatically prefixed by ROLE_
  • Authority: used as is
// These two are equivalent:
.hasRole("ADMIN") // checks ROLE_ADMIN
.hasAuthority("ROLE_ADMIN")

// Custom authorities
.hasAuthority("READ_USERS")
.hasAuthority("WRITE_USERS")

Question 9: What is CSRF and when to disable it?

Answer: CSRF (Cross-Site Request Forgery) protects against malicious requests.

Disable for stateless REST APIs (JWT):

http.csrf(csrf -> csrf.disable())

Keep enabled for applications with sessions.


Question 10: How to retrieve the connected user?

Answer:

// In a controller
@GetMapping("/me")
public User getCurrentUser(@AuthenticationPrincipal UserDetails userDetails) {
return userService.findByEmail(userDetails.getUsername());
}

// Or via SecurityContextHolder
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();

Questions 11-20: JWT​

Question 11: What is a JWT?

Answer: JSON Web Token - a token composed of 3 parts:

  1. Header: algorithm and type
  2. Payload: claims (data)
  3. Signature: integrity verification

Format: header.payload.signature (Base64 encoded)


Question 12: What are the standard claims of a JWT?

Answer:

ClaimDescription
subSubject (user)
issIssuer (emitter)
expExpiration
iatIssued at
nbfNot before
jtiJWT ID (unique)

Question 13: How to generate a JWT?

Answer:

@Service
public class JwtService {

@Value("${jwt.secret}")
private String secret;

public String generateToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 86400000))
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();
}

private Key getSigningKey() {
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));
}
}

Question 14: How to validate a JWT?

Answer:

public boolean isTokenValid(String token, UserDetails userDetails) {
try {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();

String username = claims.getSubject();
Date expiration = claims.getExpiration();

return username.equals(userDetails.getUsername())
&& !expiration.before(new Date());
} catch (JwtException e) {
return false;
}
}

Question 15: How to implement a JWT filter?

Answer:

@Component
public class JwtAuthFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) {

String header = request.getHeader("Authorization");

if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
String username = jwtService.extractUsername(token);

if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails user = userDetailsService.loadUserByUsername(username);

if (jwtService.isTokenValid(token, user)) {
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
}

chain.doFilter(request, response);
}
}

Question 16: How to configure the JWT filter?

Answer:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();
}

Question 17: What is a Refresh Token?

Answer: A long-lived token to obtain new access tokens without re-login:

  • Access Token: short-lived (15min-1h)
  • Refresh Token: long-lived (7-30 days)
// Refresh endpoint
@PostMapping("/refresh")
public TokenResponse refresh(@RequestBody RefreshRequest request) {
String refreshToken = request.getRefreshToken();
// Validate and generate new access token
}

Question 18: How to securely store the JWT secret?

Answer:

  1. Environment variables
  2. Vault (HashiCorp Vault)
  3. AWS Secrets Manager
  4. Spring Cloud Config (encrypted)
# NEVER commit the secret!
jwt:
secret: ${JWT_SECRET}

Question 19: How to invalidate a JWT?

Answer: JWTs are stateless, so not directly revocable. Solutions:

  1. Blacklist: store revoked tokens (Redis)
  2. Short expiration: tokens valid for a short time
  3. User versioning: invalidate on password change

Question 20: How to secure endpoints with annotations?

Answer:

@EnableMethodSecurity
@Configuration
public class SecurityConfig { }

@RestController
public class UserController {

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/users")
public List<User> getAllUsers() { }

@PreAuthorize("#id == authentication.principal.id or hasRole('ADMIN')")
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) { }
}

Questions 21-30: OAuth2 and Advanced Security​

Question 21: What is OAuth2?

Answer: Authorization protocol allowing an application to access a user's resources via a third-party provider (Google, GitHub, etc.) without sharing the password.


Question 22: What are the roles in OAuth2?

Answer:

  • Resource Owner: the user
  • Client: the application
  • Authorization Server: Google, GitHub...
  • Resource Server: protected API

Question 23: How to configure OAuth2 with Google?

Answer:

spring:
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
scope: openid, profile, email
http.oauth2Login(Customizer.withDefaults());

Question 24: How to customize OAuth2 login success?

Answer:

http.oauth2Login(oauth -> oauth
.successHandler((request, response, authentication) -> {
OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
userService.processOAuthUser(oauthUser);
response.sendRedirect("/dashboard");
})
);

Question 25: What is CORS?

Answer: Cross-Origin Resource Sharing - allows requests from other domains:

@Configuration
public class CorsConfig {

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:3000"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
config.setAllowedHeaders(List.of("*"));
config.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}

Question 26: How to add security headers?

Answer:

http.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives("default-src 'self'"))
.frameOptions(frame -> frame.deny())
.xssProtection(xss -> xss.enable())
);

Question 27: How to limit login attempts?

Answer: Implement a rate limiter:

@Component
public class LoginAttemptService {

private final LoadingCache<String, Integer> attemptsCache;

public void loginFailed(String ip) {
int attempts = attemptsCache.get(ip);
attemptsCache.put(ip, attempts + 1);
}

public boolean isBlocked(String ip) {
return attemptsCache.get(ip) >= MAX_ATTEMPTS;
}
}

Question 28: How to audit secure access?

Answer:

@Component
public class SecurityAuditListener {

@EventListener
public void onAuthSuccess(AuthenticationSuccessEvent event) {
log.info("Login successful: {}", event.getAuthentication().getName());
}

@EventListener
public void onAuthFailure(AuthenticationFailureBadCredentialsEvent event) {
log.warn("Login failed: {}", event.getAuthentication().getName());
}
}

Question 29: How to test security?

Answer:

@WebMvcTest(UserController.class)
@Import(SecurityConfig.class)
class UserControllerSecurityTest {

@Test
@WithMockUser(roles = "ADMIN")
void adminCanAccessAdminEndpoint() {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isOk());
}

@Test
@WithMockUser(roles = "USER")
void userCannotAccessAdminEndpoint() {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isForbidden());
}
}

Question 30: What are the best practices for Spring security?

Answer:

  1. Always encode passwords (BCrypt)
  2. Use HTTPS in production
  3. Configure CORS strictly
  4. Implement rate limiting
  5. Validate all inputs
  6. Log security events
  7. Use strong secrets and externalize them
  8. Regularly update dependencies

Score​

ScoreLevel
27-30Excellent - Security mastered
21-26Good - Some revisions needed
15-20Average - Review the chapters
Less than 15Needs improvement

Back to Module 8