Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
Chaturmind
← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 2–5 YearsSpring Security
✓ FreeIntermediate· 8 min read

Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions

How Spring Security integrates with OAuth2 (client, resource server, authorization server), CORS, SecurityContext and SecurityContextHolder, the authorization-code grant with PKCE, CSRF and when to disable it, method-level security, securing at the gateway (and still in services), SpEL rules, ADMIN/USER endpoint rules, and why digest auth is obsolete.

Published September 25, 2026


How to use this lesson

Spring Security questions reward correct mental models: the filter chain, the SecurityContext, and the three OAuth2 roles. Use Spring Security 6 APIs in every code sample, and be precise about which OAuth2 role your application plays.

Q1. How does Spring Security integrate with OAuth2?

Short answer: An application can play one or more of three OAuth2/OIDC roles, each with its own starter:

  • OAuth2 Client (spring-boot-starter-oauth2-client): oauth2Login() sends users to an identity provider (Google, Keycloak, Okta) using the authorization-code flow, and obtains tokens. The app also uses OAuth2AuthorizedClientManager to call other APIs with those tokens.
  • Resource Server (spring-boot-starter-oauth2-resource-server): oauth2ResourceServer().jwt() validates incoming bearer tokens (signature through JWKS, expiry, issuer, audience), and maps the token's scopes or roles to authorities.
  • Authorization Server (Spring Authorization Server): issues tokens, if you run your own identity provider.
@Bean
SecurityFilterChain api(HttpSecurity http) throws Exception {
    return http.authorizeHttpRequests(a -> a.anyRequest().authenticated())
               .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()))   // an API validating JWTs
               .build();
}

Key points to cover:

  • Strictly speaking, OAuth2 is authorisation (delegated access). OpenID Connect adds authentication (the ID token, user info).

Learn it in depth → Spring OAuth2 Basics

Q2. What is CORS, and how do you configure it in a Spring Boot app?

Short answer: Cross-Origin Resource Sharing is a browser mechanism. By default, browsers block JavaScript from reading responses from a different origin (scheme, host and port). A server opts in by returning Access-Control-Allow-* headers, and for non-simple requests the browser first sends a preflight OPTIONS request.

In Spring, define a CorsConfigurationSource (allowed origins, methods, headers, credentials, max age), and enable http.cors() in the security chain, so preflight requests aren't rejected by authentication. @CrossOrigin works for small cases.

Key points to cover:

  • CORS protects users' browsers, not your server. Non-browser clients ignore it completely. It's no substitute for authentication.

Q3. What are SecurityContext and SecurityContextHolder?

Short answer: The SecurityContext holds the current Authentication: the principal, credentials (usually erased after login), and the granted authorities. The SecurityContextHolder stores the context for the current thread, using a ThreadLocal by default, so any code can read who is calling.

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String user = auth.getName();

@GetMapping("/me")                                             // preferred in controllers
UserView me(@AuthenticationPrincipal Jwt jwt) { return users.view(jwt.getSubject()); }

Key points to cover:

  • Between requests: SecurityContextRepository persists the context in the HTTP session for stateful apps. Stateless apps rebuild it from the token on every request.
  • Across threads: the context doesn't follow @Async or executor threads automatically. Use DelegatingSecurityContextExecutor or a TaskDecorator.
  • Spring Security 6 no longer saves the context to the session implicitly. Custom authentication code must save it explicitly.

Q4. What is the OAuth2 authorization-code grant?

Short answer: The standard flow for users logging in through a browser:

  1. The app redirects the user to the authorization server's login and consent page.
  2. The user authenticates there. The app never sees the password.
  3. The authorization server redirects back with a short-lived, one-time authorization code.
  4. The app's backend exchanges the code (plus its client credentials) for an access token, and optionally a refresh token and an OIDC ID token.
  5. The app uses the access token to call APIs.

Key points to cover:

  • PKCE (Proof Key for Code Exchange) binds the code to the client that started the flow, which stops interception. It's mandatory for public clients (SPAs, mobile apps), and recommended for all clients (OAuth 2.1).
  • The implicit and password grants are deprecated. Don't propose them.
  • Use the state parameter to prevent CSRF on the redirect, and an exact redirect-URI allow-list.

Q5. How does Spring Security protect against CSRF, and when can you disable it?

Short answer: Spring issues a CSRF token (stored in the session, or in a cookie through CookieCsrfTokenRepository), and requires it on state-changing requests (POST, PUT, PATCH, DELETE), as a form field or header. A malicious site can make the browser send your cookies, but it can't read or guess the token, so forged requests fail.

When to disable it: only for stateless APIs that don't use cookies for authentication, where the client sends an Authorization: Bearer … header explicitly. Browsers never attach that header automatically, so CSRF doesn't apply.

Common trap: "disable CSRF for mobile clients or REST APIs". What matters isn't the client type, it's whether cookies authenticate the request. A SPA using session cookies (a BFF) still needs CSRF protection. Spring Security 6 provides SPA-friendly token handling for that case.

Q6. How do you implement method-level security, and what are the advantages?

Short answer: Enable it with @EnableMethodSecurity, then annotate service methods:

  • @PreAuthorize and @PostAuthorize, with SpEL;
  • @PreFilter and @PostFilter;
  • @Secured and JSR-250's @RolesAllowed, when enabled.
@Service
class InvoiceService {
    @PreAuthorize("hasRole('ACCOUNTANT')")
    public void approve(long invoiceId) { … }

    @PostAuthorize("returnObject.ownerId == authentication.name or hasRole('ADMIN')")
    public Invoice get(long invoiceId) { … }
}

Advantages:

  • Security sits next to the business operation, whichever entry point calls it (REST, messaging, scheduled jobs).
  • It allows fine-grained, data-aware rules: ownership, tenant, amount limits.
  • It's defence in depth, on top of URL rules.

Key points to cover:

  • It's proxy-based, so self-invocation isn't checked.

Learn it in depth → Role-Based Access Control

Q7. Your organisation routes requests through an API gateway. How would you use Spring Security to authenticate and authorise requests at the gateway?

Short answer: Configure Spring Cloud Gateway as an OAuth2 resource server that validates JWTs, applies coarse-grained rules per route (the scopes or roles needed for /admin/**), rejects bad tokens early, rate-limits by client, and relays the token downstream (or exchanges it for a narrower, service-specific token).

@Bean
SecurityWebFilterChain gateway(ServerHttpSecurity http) {
    return http.authorizeExchange(a -> a
                    .pathMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
                    .anyExchange().authenticated())
               .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()))
               .build();
}

Common trap: "then the services don't need to check security". They still do. Services should validate the token themselves, and enforce fine-grained authorisation (zero trust). Otherwise, anything that reaches a service directly (a misconfigured route, internal traffic, a compromised pod) bypasses all security.

Q8. How do you use SpEL for fine-grained access control?

Short answer: SpEL expressions in @PreAuthorize/@PostAuthorize can combine authorities, method arguments (#id), return values (returnObject), the authentication object, and custom bean methods (@beanName.method(...)):

@PreAuthorize("hasAuthority('orders:write') and @orderAccess.isOwner(#orderId, authentication)")
public void cancel(long orderId) { … }

@Component("orderAccess")
class OrderAccess {
    boolean isOwner(long orderId, Authentication auth) { return orders.ownerOf(orderId).equals(auth.getName()); }
}

Key points to cover:

  • Keep complex rules in a named bean method (testable, reusable), rather than long inline expressions.
  • For object-level permission models, PermissionEvaluator supports hasPermission(#doc, 'WRITE').

Q9. There are ADMIN and USER roles, each with different endpoints. How do you configure access control?

Short answer: Put URL rules in the SecurityFilterChain, ordered from most specific to most general, and deny by default:

@Bean
SecurityFilterChain api(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(a -> a
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .requestMatchers(HttpMethod.GET, "/api/products/**").permitAll()
            .requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
            .anyRequest().authenticated())
        .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()))
        .build();
}

Key points to cover:

  • Rules are checked in order, and the first match wins. A broad permitAll() placed early can accidentally open admin paths.
  • Consider a role hierarchy (ADMIN > USER), so admins automatically get user permissions.
  • Add method-level checks for per-record rules ("a user may only see their own orders").

Q10. What is digest authentication?

Short answer: An old HTTP authentication scheme (RFC 7616). Instead of sending the password, the client sends a hash of the username, password, a server nonce and the request details. The server checks the hash, and the nonce prevents simple replay.

Key points to cover:

  • It's obsolete in practice:
    • It's built around MD5 (weak).
    • The server must store the password in plaintext, or as a reversible or unsalted digest, which defeats modern password storage.
    • It doesn't protect the rest of the traffic.
  • Spring Security still has a DigestAuthenticationFilter, but the modern answer is HTTPS plus a form login, HTTP Basic, or OAuth2/OIDC tokens, with passwords stored using BCrypt or Argon2.

Follow-up questions this topic invites — and their answers

Q: What's the difference between an ID token and an access token? A: The ID token (OIDC, always a JWT) tells the client application who the user is. The access token is presented to APIs to authorise calls. APIs should accept access tokens, not ID tokens.

Q: What's the difference between hasRole and hasAuthority? A: hasRole('ADMIN') checks for the authority ROLE_ADMIN, because the prefix is added for you. hasAuthority checks the exact string, which is typical for JWT scopes such as SCOPE_orders.read.

Q: How do you map custom JWT claims to roles? A: Configure a JwtAuthenticationConverter with a JwtGrantedAuthoritiesConverter (set the claim name and prefix), or write a converter that reads, for example, Keycloak's realm_access.roles.

Q: Where should authorisation logic live: the gateway, the service, or the database? A: Coarse checks at the gateway (is this caller valid, and allowed on this API at all). Business authorisation in the service (ownership, limits, workflow state). Data-level safety nets (tenant filters, row-level security) where the risk justifies them.

Previous

External APIs, Files, GraphQL & WebFlux — Interview Questions

Next

Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

AI Tutor

Lesson: Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.