Top Interview Questions
Spring Security is a powerful and highly customizable framework that provides authentication, authorization, and protection against common security threats for Java applications. It is a part of the larger Spring ecosystem and is widely used in enterprise-level applications, especially those built using Spring Boot and Spring MVC.
Security is a critical requirement in modern applications, as they handle sensitive data such as user credentials, personal information, and financial records. Spring Security simplifies the process of implementing robust security mechanisms by offering a declarative and flexible approach.
Spring Security is a Java-based security framework that focuses on securing applications at both the web request level and the method level. It uses a combination of filters, interceptors, and configuration components to ensure that only authenticated and authorized users can access protected resources.
At its core, Spring Security provides:
Authentication – Verifying who the user is
Authorization – Determining what the user is allowed to do
Protection against common attacks – Such as CSRF, session fixation, and clickjacking
Authentication is the process of verifying the identity of a user. Spring Security supports multiple authentication mechanisms, including:
Username and password authentication
Form-based login
HTTP Basic authentication
OAuth2 and OpenID Connect
LDAP authentication
JWT (JSON Web Token) authentication
Spring Security uses an AuthenticationManager to handle authentication requests. Once authentication is successful, an Authentication object is stored in the SecurityContext.
Authorization determines whether an authenticated user has permission to access a specific resource. It is typically based on:
Roles (e.g., ROLE_ADMIN, ROLE_USER)
Authorities or privileges
Custom access rules
Spring Security supports role-based access control (RBAC) and fine-grained authorization using annotations like:
@PreAuthorize
@PostAuthorize
@Secured
@RolesAllowed
The SecurityContext holds security-related information about the currently authenticated user. It is stored in a thread-local variable and is accessible throughout the request lifecycle.
The main object stored in the SecurityContext is the Authentication object, which contains:
Principal (user details)
Credentials
Granted authorities
Spring Security follows a filter-based architecture. Every incoming HTTP request passes through a chain of security filters before reaching the application.
The Security Filter Chain is a sequence of filters that perform tasks such as:
Authenticating requests
Validating sessions
Checking access permissions
Protecting against CSRF attacks
Some important filters include:
UsernamePasswordAuthenticationFilter
BasicAuthenticationFilter
CsrfFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
Each filter has a specific responsibility, making the framework modular and extensible.
Spring Boot makes it extremely easy to integrate Spring Security. By simply adding the dependency, Spring Boot enables default security configurations automatically.
When Spring Security is added:
All endpoints are secured by default
A default login page is generated
A default user is created with a randomly generated password
CSRF protection is enabled
These defaults are helpful for quick setup but are usually customized in real-world applications.
Spring Security can be configured using:
Java-based configuration
Annotations
YAML or properties files
Modern Spring applications prefer Java-based configuration using a SecurityFilterChain bean.
A typical configuration includes:
Defining public and protected URLs
Configuring authentication mechanisms
Setting up password encoders
Managing sessions
Spring Security uses a declarative approach, making configurations readable and maintainable.
UserDetails is an interface that represents user information required by Spring Security. It contains:
Username
Password
Account status (enabled, expired, locked)
Authorities
UserDetailsService is responsible for loading user-specific data during authentication. It retrieves user details from:
In-memory storage
Database
LDAP
External services
Custom implementations of UserDetailsService are commonly used in real-world applications.
Spring Security emphasizes secure password storage. Passwords should never be stored in plain text.
Spring Security provides the PasswordEncoder interface with implementations like:
BCryptPasswordEncoder
SCryptPasswordEncoder
Argon2PasswordEncoder
BCrypt is the most commonly used encoder because it is adaptive and resistant to brute-force attacks.
Access to URLs can be restricted based on roles or authorities:
Public URLs (e.g., login, registration)
Protected URLs (e.g., admin dashboard)
Spring Security supports method-level authorization using annotations:
@PreAuthorize("hasRole('ADMIN')")
@PreAuthorize("hasAuthority('READ_PRIVILEGE')")
This approach ensures security at the business logic layer.
CSRF (Cross-Site Request Forgery) is a common web vulnerability. Spring Security enables CSRF protection by default.
A unique CSRF token is generated per session
The token must be included in state-changing requests (POST, PUT, DELETE)
Requests without a valid token are rejected
For REST APIs using JWT, CSRF protection is often disabled.
Spring Security provides powerful session management features, such as:
Session fixation protection
Concurrent session control
Session timeout handling
Logout functionality
These features help protect applications from session-based attacks.
Spring Security handles security-related exceptions such as:
Authentication failures
Access denied errors
Session expiration
Custom error pages or JSON responses can be configured for better user experience, especially in REST APIs.
Spring Security is widely used to secure RESTful APIs.
Common approaches include:
HTTP Basic Authentication (simple but less secure)
JWT-based authentication (stateless and scalable)
OAuth2 and OpenID Connect (used in modern microservices)
JWT is particularly popular because it allows stateless authentication, reducing server-side session management.
Some key advantages include:
Highly customizable and extensible
Integrates seamlessly with Spring ecosystem
Provides comprehensive security features out of the box
Supports modern authentication standards
Backed by strong community and documentation
Despite its power, Spring Security has a steep learning curve for beginners. The filter chain and configuration options can be complex initially. However, once understood, it provides unmatched flexibility and control over application security.
Answer:
Spring Security is a powerful and customizable framework that provides authentication, authorization, and protection against common security attacks in Java-based applications, especially Spring applications.
Key features:
Authentication: Verifying user identity.
Authorization: Controlling access to resources.
Protection against attacks: CSRF, Session Fixation, Clickjacking, etc.
Integration with Spring applications: Easily integrates with Spring Boot and Spring MVC.
Answer:
Authentication: Process of verifying the user’s identity (e.g., login).
Authorization: Process of granting user access to specific resources based on roles/permissions.
Principal: Represents the currently logged-in user.
GrantedAuthority: Represents a permission or role granted to a user.
SecurityContext: Holds security-related information for the current execution thread.
Filters: Spring Security uses a chain of filters to intercept HTTP requests.
Answer:
| Feature | Authentication | Authorization |
|---|---|---|
| Purpose | Verify identity | Verify access rights |
| When | During login | After login |
| Example | Username/password | Role-based access (ADMIN, USER) |
Answer:
In-Memory Authentication: Stores users in the application memory (for testing).
JDBC Authentication: Stores users in a database.
LDAP Authentication: Uses LDAP server for authentication.
OAuth2 / OpenID Connect: Authentication using external identity providers like Google, Facebook.
UserDetails and UserDetailsService in Spring Security?Answer:
UserDetails: Represents the core user information (username, password, roles).
UserDetailsService: Interface used to fetch user details from a custom source, such as a database.
Example:
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Fetch user from database
return new User(username, "password", List.of(new SimpleGrantedAuthority("ROLE_USER")));
}
}
Answer:
Web Security: Securing web applications (HTTP requests, endpoints).
Method Security: Securing methods using annotations like @PreAuthorize and @Secured.
OAuth2 Security: Using third-party providers for authentication.
Answer:
| Annotation | Description |
|---|---|
@EnableWebSecurity |
Enables web security configuration. |
@PreAuthorize |
Defines access rules before method execution. |
@PostAuthorize |
Checks access rules after method execution. |
@Secured |
Allows access to methods based on roles. |
@RolesAllowed |
JSR-250 annotation for role-based access. |
Answer:
By default, Spring Security provides form-based login and HTTP Basic Authentication.
Form-based login: Users log in via a web form.
HTTP Basic: Users send username/password in the HTTP request header.
Answer:
You can configure Spring Security using Java configuration (recommended) or XML (legacy).
Example (Java configuration):
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/", "/home").permitAll()
.and()
.formLogin();
}
}
Answer:
CSRF (Cross-Site Request Forgery) is an attack where unauthorized commands are sent from a user the website trusts.
Spring Security CSRF protection:
Enabled by default for all state-changing requests (POST, PUT, DELETE).
Uses a CSRF token in forms to prevent attacks.
Example:
<form method="post" action="/submit">
<input type="hidden" name="_csrf" value="${_csrf.token}"/>
...
</form>
hasRole() and hasAuthority() in Spring Security?Answer:
hasRole("ROLE_USER"): Checks if the user has a specific role. Spring Security automatically adds ROLE_ prefix.
hasAuthority("USER_PRIVILEGE"): Checks for specific authority/permission, no prefix is added automatically.
SecurityContextHolder?Answer:
SecurityContextHolder is a container that stores security context (authentication information) for the current thread.
Example:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
Answer:
| Feature | Stateful | Stateless |
|---|---|---|
| Session | Stored on server | Not stored on server |
| Authentication | Via session ID | Via token (e.g., JWT) |
| Example | Traditional login | REST APIs with JWT |
Answer:
Steps to implement JWT:
User logs in with credentials.
Server validates credentials and generates JWT.
Client sends JWT in Authorization header for subsequent requests.
Server validates JWT in a filter before accessing endpoints.
Example of header:
Authorization: Bearer <JWT_TOKEN>
Answer:
Use antMatchers in configuration:
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated();
Answer:
Spring Security uses a chain of servlet filters to process HTTP requests.
Common filters include:
UsernamePasswordAuthenticationFilter: Handles login requests.
BasicAuthenticationFilter: Handles HTTP Basic authentication.
CsrfFilter: Handles CSRF protection.
Answer:
Passwords should be stored in encoded (hashed) format for security. Spring Security provides encoders like:
BCryptPasswordEncoder
NoOpPasswordEncoder (for testing only)
SCryptPasswordEncoder
Example:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Answer:
Add @EnableGlobalMethodSecurity(prePostEnabled = true) in configuration.
Use annotations on methods:
@PreAuthorize("hasRole('ADMIN')")
public void adminTask() {
...
}
Answer:
Spring Security: Focuses on authentication, authorization, and protecting resources.
Spring Session: Manages HTTP session data (useful for distributed sessions, e.g., in Redis).
Answer:
Use stateless authentication (JWT tokens).
Disable session creation:
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Protect endpoints with roles/authorities.
Enable CORS if needed for cross-origin requests.
WebSecurityConfigurerAdapter?Answer:
WebSecurityConfigurerAdapter is a base class provided by Spring Security to customize web security configuration.
By extending it, you can override methods to configure authentication, authorization, CSRF, and session management.
Example:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll();
}
}
Note: In Spring Security 6 / Spring Boot 3,
WebSecurityConfigurerAdapteris deprecated; the recommended approach is bean-based configuration.
Answer:
Authentication providers are used to validate credentials. Common types:
DaoAuthenticationProvider: Uses UserDetailsService to fetch user data from DB.
LdapAuthenticationProvider: Uses LDAP for authentication.
AnonymousAuthenticationProvider: Handles anonymous users.
PreAuthenticatedAuthenticationProvider: Used when authentication is done externally.
@EnableWebSecurity and @EnableGlobalMethodSecurity?Answer:
| Annotation | Purpose |
|---|---|
@EnableWebSecurity |
Enables Spring Security for web-based requests. |
@EnableGlobalMethodSecurity |
Enables method-level security using annotations like @PreAuthorize and @Secured. |
Example:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig { ... }
Answer:
HTTP Basic authentication is a simple authentication scheme where username and password are sent in the HTTP header (base64 encoded).
Example configuration:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
Note: Not recommended for production unless used over HTTPS.
Answer:
Form-based authentication uses a custom login form. Spring Security automatically processes login requests and authenticates users.
Example:
http
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
loginPage("/login") → Custom login page.
permitAll() → Allows everyone to access login page.
Answer:
Method-level security controls access to specific methods rather than whole URLs. Useful when:
Certain actions are restricted by role.
Business logic requires fine-grained access control.
Annotations:
@PreAuthorize – Check before method execution.
@PostAuthorize – Check after method execution.
@Secured – Role-based access at method level.
Example:
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { ... }
Remember-Me authentication in Spring Security?Answer:
Remember-Me authentication allows users to stay logged in even after closing the browser.
Implemented using cookies.
Useful for improving user experience.
Example:
http
.rememberMe()
.key("uniqueAndSecret")
.tokenValiditySeconds(86400); // 1 day
ROLE_USER and ROLE_ADMIN in Spring Security?Answer:
These are role names used to define user access.
ROLE_USER → General user access.
ROLE_ADMIN → Admin access with elevated permissions.
Spring Security uses prefix ROLE_ by default when checking roles.
Answer:
Spring Security provides a built-in logout mechanism.
Example:
http
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
logoutUrl() → Endpoint to trigger logout.
logoutSuccessUrl() → Redirect after logout.
invalidateHttpSession() → Clears the session.
deleteCookies() → Deletes cookies like JSESSIONID.
Answer:
Session Fixation: Attacker fixes a user session to hijack authentication.
Spring Security prevention: Creates a new session on login.
Configuration example:
http
.sessionManagement()
.sessionFixation().migrateSession();
Answer:
CORS (Cross-Origin Resource Sharing): Controls which domains can access your API.
In Spring Security, enable it using:
http.cors().and().csrf().disable();
Define a CorsConfigurationSource bean to specify allowed origins, methods, and headers.
Answer:
User logs in and server validates credentials.
Generate JWT and send it to the client.
Client sends JWT in Authorization header for API calls.
Create a JWT filter to validate the token before accessing endpoints.
JWT filter example:
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
// validate token
chain.doFilter(request, response);
}
}
@PreAuthorize and @Secured?Answer:
| Annotation | Description |
|---|---|
@PreAuthorize |
Supports SpEL expressions for fine-grained access control. Can check roles, permissions, or custom expressions. |
@Secured |
Simple role-based access control. Checks only role names. |
Example:
@PreAuthorize("hasRole('ADMIN') and #id == authentication.principal.id")
public void deleteUser(Long id) { ... }
@Secured("ROLE_ADMIN")
public void deleteUser(Long id) { ... }
AuthenticationManager?Answer:
Core interface responsible for processing authentication requests.
Delegates authentication to one or more AuthenticationProviders.
Example:
@Autowired
private AuthenticationManager authManager;
Authentication auth = authManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password)
);
Answer:
Actuator exposes endpoints for monitoring. Secure them using Spring Security.
Example:
management.endpoints.web.exposure.include=health,info
management.endpoint.health.show-details=always
http
.authorizeRequests()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/**").hasRole("ADMIN");
Answer:
OAuth2 is an authorization framework that allows applications to access resources on behalf of a user without exposing credentials.
Spring Security supports OAuth2 for both Authorization Server and Resource Server.
Key components:
Resource Owner: User.
Client: Application requesting access.
Authorization Server: Issues access tokens.
Resource Server: Protects APIs and validates tokens.
Example (Resource Server configuration):
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(auth -> auth.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt());
return http.build();
}
}
Answer:
Authentication: Contains full security information of the current user, including credentials, authorities, and details.
Principal: Represents the user identity (username, user object) in a simpler form.
Example:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Object principal = auth.getPrincipal();
GrantedAuthority in Spring Security?Answer:
GrantedAuthority represents permissions or roles granted to a user.
Roles are usually prefixed with ROLE_.
Used by Spring Security to check access control.
Example:
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
User user = new User("john", "password", authorities);
PasswordEncoder and why is it important?Answer:
PasswordEncoder is used to hash/encode passwords for secure storage.
Prevents storing passwords in plain text.
Common implementations:
BCryptPasswordEncoder → Recommended for production.
NoOpPasswordEncoder → Plain text (for testing only).
SCryptPasswordEncoder → Stronger encoding.
Example:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Answer:
REST APIs typically use stateless authentication (JWT, OAuth2).
Disable CSRF for stateless APIs.
Use a filter to validate JWT for each request.
Example:
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests().anyRequest().authenticated();
antMatchers, mvcMatchers, and regexMatchers?Answer:
| Matcher Type | Description | Example |
|---|---|---|
antMatchers |
Uses Ant-style path patterns | /admin/** |
mvcMatchers |
Uses Spring MVC’s path matching | /user/{id} |
regexMatchers |
Uses regular expressions | /user/[0-9]+ |
Example:
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.mvcMatchers("/user/{id}").hasRole("USER")
.regexMatchers("/product/[0-9]+").authenticated();
OncePerRequestFilter in Spring Security?Answer:
A base filter that ensures filter logic is executed only once per request.
Commonly used to implement JWT validation filters.
Example:
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Validate JWT
filterChain.doFilter(request, response);
}
}
Answer:
CORS (Cross-Origin Resource Sharing) is required for APIs accessed from different domains.
Configuration Example:
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:3000"));
configuration.setAllowedMethods(List.of("GET","POST","PUT","DELETE"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
Answer:
| Action | Default URL |
|---|---|
| Login page | /login |
| Login processing | /login (POST) |
| Logout | /logout |
| Default success redirect | / |
These can be customized using
formLogin()andlogout()in configuration.
Answer:
Controls how HTTP sessions are created and managed.
Prevents session fixation, concurrent session issues.
Common strategies:
SessionCreationPolicy.IF_REQUIRED → Default, create if needed.
SessionCreationPolicy.STATELESS → No session, for REST APIs.
SessionCreationPolicy.ALWAYS → Always create a session.
SessionCreationPolicy.NEVER → Never create, but use if exists.
Example:
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Answer:
Spring Security provides AccessDeniedHandler to customize behavior when a user tries to access a forbidden resource.
Example:
http.exceptionHandling()
.accessDeniedHandler((request, response, ex) -> {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied!");
});
Answer:
| Feature | Stateful | Stateless |
|---|---|---|
| Session | Stored on server | Not stored |
| Authentication | Session ID | Token (JWT) |
| Example | Traditional web apps | REST APIs |
| Pros | Can store user info on server | Scales better for APIs |
Answer:
User logs in → server validates credentials.
Server generates JWT → returns to client.
Client sends JWT in Authorization header.
Spring Security filter validates JWT → authenticates request.
Example Filter:
public class JwtAuthFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
// validate token
}
chain.doFilter(request, response);
}
}
ROLE_ and authority in Spring Security?Answer:
Role: A higher-level grouping of permissions; automatically prefixed with ROLE_.
Authority: Fine-grained permission/privilege; no automatic prefix.
Example:
new SimpleGrantedAuthority("ROLE_ADMIN"); // role
new SimpleGrantedAuthority("WRITE_PRIVILEGE"); // authority
Answer:
Restrict sensitive endpoints like /actuator/env or /actuator/beans.
Example configuration:
http.authorizeRequests()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/**").hasRole("ADMIN");
Answer:
| Aspect | Freshers | Experienced (4 years) |
|---|---|---|
| Focus | Basics: Authentication, Authorization, Roles | Advanced: JWT, OAuth2, SSO, Microservices Security, Method-level security, Custom filters |
| Knowledge Depth | Simple config, in-memory authentication | Production-grade security, performance, custom providers, token-based auth |
| Implementation | Basic login/logout | REST API security, JWT, OAuth2 integration, LDAP, CORS, CSRF fine-tuning |
Answer:
Steps:
Authentication Service: Validate credentials, generate JWT with claims (roles, expiry, etc.).
Client: Stores JWT and sends it in Authorization header.
Resource Service (Microservice): Uses a JWT filter to validate token.
Token Validation: Use io.jsonwebtoken or Spring Security JWT support.
Refresh Tokens: Optional, to extend session without login.
Example Filter:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
String jwt = token.substring(7);
if (jwtUtil.validateToken(jwt)) {
UsernamePasswordAuthenticationToken auth = jwtUtil.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
chain.doFilter(request, response);
}
}
Answer:
Use RoleHierarchy to define parent-child relationships between roles.
Allows automatic access if a higher-level role has all lower-level permissions.
Example:
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_ADMIN > ROLE_MANAGER \n ROLE_MANAGER > ROLE_USER");
return hierarchy;
}
ROLE_ADMIN inherits ROLE_MANAGER and ROLE_USER permissions automatically.
Answer:
CSRF protection is disabled for stateless APIs (JWT-based).
For stateful apps, Spring Security adds CSRF tokens automatically.
Example:
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Stateless REST APIs rely on JWT tokens in headers, making CSRF irrelevant.
Answer:
OAuth2: Authorization framework to allow apps to access user resources without sharing credentials.
Spring Security 5+ provides native support for OAuth2 login, authorization, and resource server.
Authorization Server (Spring Authorization Server) issues JWT access tokens.
Resource Server validates JWT:
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(auth -> auth.anyRequest().authenticated())
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
Supports OpenID Connect for SSO.
Answer:
Use @EnableGlobalMethodSecurity(prePostEnabled = true) in config.
Annotations: @PreAuthorize, @PostAuthorize.
Example:
@PreAuthorize("hasRole('ADMIN') and #userId == authentication.principal.id")
public void deleteUser(Long userId) { ... }
@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long docId) { ... }
Allows fine-grained access control at method level based on roles, attributes, or custom conditions.
Answer:
SSO allows single authentication for multiple applications.
Common approaches: OAuth2 / OpenID Connect.
Spring Security supports OAuth2 client configuration for SSO.
Example (Google login):
spring.security.oauth2.client.registration.google.client-id=xxx
spring.security.oauth2.client.registration.google.client-secret=xxx
spring.security.oauth2.client.registration.google.scope=openid,profile,email
Application handles authentication automatically via the OAuth2 provider.
Answer:
JWT tokens for stateless authentication.
OAuth2 / OpenID Connect for centralized authentication.
API Gateway handles authentication & token validation for all microservices.
Spring Cloud Gateway + ReactiveJwtAuthenticationConverter for reactive services.
Best Practices:
Centralize authentication.
Avoid sharing sessions across services.
Validate tokens in every service.
Use role/authority claims inside JWT.
Answer:
Configure LDAP server URL and search filters.
Use LdapAuthenticationProvider to authenticate users.
Example:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org");
}
Works well for enterprise-level apps.
Answer:
Create a custom AuthenticationProvider by implementing AuthenticationProvider.
Useful when authentication requires database, API call, or external system validation.
Example:
@Component
public class CustomAuthProvider implements AuthenticationProvider {
@Autowired private UserService userService;
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
String username = auth.getName();
String password = auth.getCredentials().toString();
User user = userService.loadUser(username);
if(user != null && passwordEncoder.matches(password, user.getPassword())) {
return new UsernamePasswordAuthenticationToken(username, password, user.getAuthorities());
}
throw new BadCredentialsException("Invalid credentials");
}
@Override
public boolean supports(Class<?> auth) {
return auth.equals(UsernamePasswordAuthenticationToken.class);
}
}
Answer:
Prevent multiple logins with same credentials or limit session concurrency.
Use ConcurrentSessionControlAuthenticationStrategy.
Example:
http.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.expiredUrl("/login?expired");
Ensures only one active session per user.
Answer:
Authorization Server: Issues JWT with claims.
API Gateway: Validates token before routing requests.
Resource Services: Validate JWT signature and extract roles/claims.
Token validation:
Use NimbusJwtDecoder or Spring Security’s built-in JWT decoder.
Check expiry, issuer, signature, audience.
Answer:
JWT is short-lived; refresh tokens are long-lived tokens for getting new JWT without login.
Workflow:
User logs in → receives JWT + refresh token.
JWT expires → client sends refresh token to auth endpoint.
Auth server validates refresh token → issues new JWT.
Best Practices:
Store refresh tokens securely.
Implement revocation mechanisms.
Use HTTPS only.
Answer:
Use SpEL expressions to check tenant-specific access.
Example:
@PreAuthorize("#tenantId == authentication.principal.tenantId")
public void updateTenantData(Long tenantId, Data data) { ... }
Ensures users access only their tenant data.
Answer:
Enable debug logs:
logging.level.org.springframework.security=DEBUG
Check SecurityContext for authentication.
Use filters ordering to ensure custom filters are invoked.
Verify JWT claims, roles, authorities.
Use Actuator endpoints for monitoring secured APIs.
Answer:
| Feature | OAuth2 | JWT |
|---|---|---|
| Purpose | Authorization framework, can include authentication | Token-based authentication and authorization |
| Token type | Access token (can be JWT) | JWT (self-contained) |
| Use case | Third-party login, SSO, API authorization | Stateless REST APIs |
| Expiry | Usually short-lived, can have refresh token | Encodes expiry in token itself |
OAuth2 can use JWT as the token format. JWT is just a token standard, while OAuth2 is a protocol.
Answer:
AuthenticationManager: Delegates authentication requests to one or more AuthenticationProviders.
AuthenticationProvider: Actually performs authentication (checks credentials against DB, LDAP, API, etc.).
Example Flow:
User submits credentials → AuthenticationManager → AuthenticationProvider → SecurityContextHolder
Answer:
Include roles in JWT claims (roles or authorities).
Create JWT filter in each microservice to validate token and extract roles.
Use Spring Security annotations or antMatchers for access control:
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated();
Use method-level security (@PreAuthorize) for finer control.
Answer:
| Strategy | Description | Use Case |
|---|---|---|
IF_REQUIRED |
Default, creates session only if needed | Traditional web apps |
ALWAYS |
Always creates session | Rarely used |
NEVER |
Never creates session, but uses if exists | REST APIs with some session needs |
STATELESS |
No sessions, every request is authenticated independently | REST APIs, microservices |
Example:
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Answer:
Use LDAP authentication provider with PasswordCompareAuthenticator and a PasswordEncoder.
Example:
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
.passwordAttribute("userPassword");
Ensures passwords stored in LDAP are hashed securely.
Answer:
Register app with OpenID provider (Google, Okta, Keycloak).
Configure Spring Security OAuth2 client:
spring.security.oauth2.client.registration.google.client-id=xxx
spring.security.oauth2.client.registration.google.client-secret=xxx
spring.security.oauth2.client.registration.google.scope=openid,profile,email
Enable OAuth2 login:
http.oauth2Login()
.loginPage("/oauth2/authorization/google")
.defaultSuccessUrl("/dashboard");
Access user info from OAuth2AuthenticationToken.
Answer:
CSRF attacks rely on cookies and sessions, so JWT-based stateless APIs are inherently safe.
Therefore, disable CSRF for stateless REST endpoints:
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Only use CSRF protection for form-based stateful apps.
Answer:
Used when authentication logic cannot rely solely on UserDetailsService.
Examples: authentication against external API, database, LDAP, or multi-factor authentication.
Example:
@Component
public class CustomAuthProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
// Custom authentication logic
}
@Override
public boolean supports(Class<?> auth) {
return auth.equals(UsernamePasswordAuthenticationToken.class);
}
}
Answer:
Use SpEL expressions to validate tenant access:
@PreAuthorize("#tenantId == authentication.principal.tenantId")
public void updateTenantData(Long tenantId, Data data) { ... }
Ensures users cannot access data from other tenants.
Answer:
Issue short-lived JWT and long-lived refresh token during login.
Client stores refresh token securely.
When JWT expires, client calls /refresh endpoint with refresh token.
Server validates refresh token → issues new JWT.
Security best practices:
Store refresh tokens in secure DB.
Implement revocation mechanism.
Use HTTPS only.
Answer:
Enable debug logs:
logging.level.org.springframework.security=DEBUG
Verify SecurityContext to check current authentication.
Use SecurityContextHolder.getContext().getAuthentication().
Check filter chain order to ensure custom filters are executed.
Validate JWT signature, expiry, roles, and claims.
Use Spring Boot Actuator endpoints for monitoring.
Answer:
Spring Security does not provide rate limiting out-of-the-box.
Use filters or external solutions (like Spring Cloud Gateway, Redis, Bucket4J).
Example filter-based approach:
@Component
public class RateLimitFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
// Check request count for IP / user
chain.doFilter(request, response);
}
}
Answer:
Configure multiple AuthenticationProviders in order:
auth.authenticationProvider(customAuthProvider)
.authenticationProvider(daoAuthenticationProvider);
Spring Security tries each provider until authentication succeeds.
Example: LDAP + database fallback.
Answer:
Restrict access to sensitive endpoints like /actuator/env or /actuator/beans.
http.authorizeRequests()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/**").hasRole("ADMIN");
For OAuth2/JWT-secured APIs, attach token validation to actuator endpoints.
Answer:
Track user actions (login, logout, data changes).
Use Spring Security events (AuthenticationSuccessEvent, AuthenticationFailureEvent) for login/logout audit.
Log important actions in DB for compliance.
Example:
@Component
public class AuthEventListener {
@EventListener
public void onAuthenticationSuccess(AuthenticationSuccessEvent event) {
String username = event.getAuthentication().getName();
// Save audit record
}
}
Answer:
Multi-factor authentication adds an extra layer beyond username/password.
Typical approach: Step 1: Username/password verification → Step 2: OTP or token verification.
Implementation steps:
Custom AuthenticationProvider to validate credentials.
Generate OTP or push notification to user.
Custom filter to handle the second factor.
Update SecurityContext only after successful MFA.
Example:
public class OtpAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
// Validate OTP after password verification
}
}
Answer:
Stateless Authentication: Use JWT for token-based auth.
Gateway Validation: API Gateway validates JWT before routing.
Service-to-Service Auth: Use OAuth2 client credentials flow or mutual TLS.
Roles and Claims: Include roles and permissions in JWT.
Centralized Auth Server: Use Keycloak, Okta, or Spring Authorization Server for token issuance.
Best practices:
No session sharing between services.
Each service validates tokens independently.
Log and audit critical actions.
SecurityContext and Authentication in Spring Security?Answer:
SecurityContext: Holds the security information for the current execution thread.
Authentication: Represents the principal, credentials, and authorities of the currently authenticated user.
Example:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
Collection<? extends GrantedAuthority> roles = auth.getAuthorities();
Answer:
Short-lived JWT + refresh token.
Rotation: Each time the refresh token is used, issue a new refresh token and invalidate the old one.
Prevents replay attacks.
Implementation Steps:
Issue JWT + refresh token at login.
Client uses refresh token → server validates and issues new JWT + refresh token.
Store refresh token in DB or cache with expiration.
Revoke old token after use.
Answer:
Used for service-to-service communication (no user involved).
Implementation:
spring.security.oauth2.client.registration.my-service.client-id=xxx
spring.security.oauth2.client.registration.my-service.client-secret=xxx
spring.security.oauth2.client.registration.my-service.authorization-grant-type=client_credentials
Spring Security automatically requests a JWT token from auth server and attaches it to outgoing requests.
Answer:
Use @PreAuthorize with SpEL expressions to check custom permissions.
Example:
@PreAuthorize("@permissionEvaluator.hasPermission(authentication, #document, 'EDIT')")
public void editDocument(Document document) { ... }
PermissionEvaluator is a custom bean that checks fine-grained permissions.
Answer:
Limit login attempts using:
Custom authentication failure handlers
Cache or DB to track failed attempts per user/IP
Lock account temporarily after N failed attempts
Example:
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception) throws IOException {
// Increment failed attempts in DB or cache
}
}
Answer:
Use RoleHierarchy to define parent-child relationships.
Allows automatic inheritance of lower-level roles.
Example:
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_ADMIN > ROLE_MANAGER \n ROLE_MANAGER > ROLE_USER");
return hierarchy;
}
ROLE_ADMIN automatically has ROLE_MANAGER and ROLE_USER permissions.
Answer:
Keycloak acts as an authorization server issuing JWT tokens.
Spring Boot + Spring Security can act as resource server:
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
Use Keycloak adapters for session-based authentication if needed.
Answer:
Multi-tenancy requires restricting data access per tenant.
Approaches:
Include tenant ID in JWT claims.
Use SpEL in method-level security:
@PreAuthorize("#tenantId == authentication.principal.tenantId")
public void accessTenantData(Long tenantId) { ... }
Filter repository queries using tenant ID from SecurityContext.
Answer:
Capture authentication events and critical user actions.
Use ApplicationListener for events:
@Component
public class SecurityEventListener {
@EventListener
public void onAuthenticationSuccess(AuthenticationSuccessEvent event) {
String username = event.getAuthentication().getName();
// log to DB or file
}
}
For method-level auditing, use AOP or @PreAuthorize with custom logs.
Answer:
Password grant flow allows exchanging username/password for access token.
Not recommended for public clients; used for trusted clients.
Implementation:
Configure Authorization Server with password grant support.
Client sends POST request with credentials → receives JWT.
Resource server validates JWT as usual.
Answer:
Use @EnableWebSocketMessageBroker with security configuration.
Protect endpoints using SimpMessageType and roles.
Example:
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/app/admin/**").hasRole("ADMIN")
.anyMessage().authenticated();
}
Answer:
Configure maximum sessions per user to prevent multiple logins:
http.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.expiredUrl("/login?expired");
Options:
Prevent new login if max reached
Expire old session on new login
Answer:
Configure Spring Security with custom login page:
http.formLogin()
.loginPage("/login")
.loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/home")
.failureUrl("/login?error=true");
Use AuthenticationFailureHandler for advanced error handling.
Answer:
In microservices, each service should validate JWT independently.
Steps:
Extract token from Authorization header.
Decode and validate signature using public key / secret.
Verify claims (expiry, issuer, roles, tenantId).
Set SecurityContext for request.
Example Filter:
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
@Autowired private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
String jwt = token.substring(7);
if (jwtUtil.validateToken(jwt)) {
SecurityContextHolder.getContext().setAuthentication(jwtUtil.getAuthentication(jwt));
}
}
chain.doFilter(request, response);
}
}
Answer:
Resource Server validates JWT access tokens issued by an Authorization Server.
Configuration:
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(auth -> auth.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt());
return http.build();
}
}
Supports audience, issuer validation and integrates with JWT claims for authorization.
Answer:
Common for user authentication with third-party providers (Google, Okta).
Flow:
Client redirects user to Authorization Server.
User authenticates and grants access.
Authorization server returns authorization code.
Client exchanges code for access token / refresh token.
Spring Security handles token validation automatically using oauth2Login().
Example:
http.oauth2Login()
.loginPage("/oauth2/authorization/google")
.defaultSuccessUrl("/dashboard");
Answer:
JWT tokens are stateless and short-lived.
Refresh workflow:
Client stores refresh token.
When JWT expires, call /refresh endpoint with refresh token.
Validate refresh token → issue new JWT (and optionally new refresh token).
Security best practices:
Store refresh tokens securely.
Use HTTPS only.
Implement revocation mechanism.
Answer:
Use AuthenticationSuccessHandler and AuthenticationFailureHandler.
Useful for logging, redirecting, or triggering additional logic.
Example:
http.formLogin()
.loginPage("/login")
.successHandler((request, response, auth) -> response.sendRedirect("/dashboard"))
.failureHandler((request, response, exception) -> response.sendRedirect("/login?error"));
Answer:
WebSocket endpoints can be secured with Spring Security’s message broker interceptors.
Configure access for SimpMessageType and roles.
Example:
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/app/admin/**").hasRole("ADMIN")
.anyMessage().authenticated();
}
Answer:
Session fixation occurs when an attacker fixes the session ID to gain unauthorized access.
Spring Security prevents this by migrating session after login.
Example:
http.sessionManagement()
.sessionFixation().migrateSession();
Other options: newSession(), none() depending on use case.
Answer:
Multi-tenancy restricts user access to tenant-specific data.
Strategies:
Include tenant ID in JWT claims.
Use SpEL in method-level security:
@PreAuthorize("#tenantId == authentication.principal.tenantId")
public void accessTenantData(Long tenantId) { ... }
Filter database queries using tenant ID from SecurityContext.
Answer:
Use Spring Security events for login/logout audit.
Use AOP or event listeners for method-level auditing.
Example:
@Component
public class SecurityAuditListener {
@EventListener
public void onAuthenticationSuccess(AuthenticationSuccessEvent event) {
String username = event.getAuthentication().getName();
// Log to DB or audit service
}
}
Answer:
Strategies:
Limit login attempts per user/IP.
Use Redis or in-memory cache to track failed attempts.
Temporarily lock accounts after N failed attempts.
Implement rate limiting on login endpoint.
Example:
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException {
// Increment failed attempts and block if necessary
}
}
Answer:
Define parent-child relationships between roles using RoleHierarchy.
Example:
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_ADMIN > ROLE_MANAGER \n ROLE_MANAGER > ROLE_USER");
return hierarchy;
}
ROLE_ADMIN automatically inherits all lower roles’ permissions.
Answer:
Keycloak provides centralized authentication and SSO capabilities.
Configure Spring Boot as resource server:
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
For session-based apps, use Keycloak Spring Boot adapter.
Answer:
Prevent multiple logins or limit active sessions per user:
http.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.expiredUrl("/login?expired");
Options:
Block new logins
Expire oldest session
Answer:
Custom filters can perform authentication, authorization, logging, or token validation.
Extend OncePerRequestFilter or GenericFilterBean.
Register filter in SecurityFilterChain at appropriate order:
http.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class);
Answer:
Configure CORS to allow requests from frontend domains.
Example:
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:3000"));
configuration.setAllowedMethods(List.of("GET","POST","PUT","DELETE"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
http.cors().and().csrf().disable();