Week 6 Day 4 — CSRF, CORS, Sessions, Stateless APIs, and JWT Mental Model
Goal
Today I want to understand important REST API security configuration topics.
Main questions:
- What is CSRF?
- When should CSRF be enabled?
- When is CSRF commonly disabled?
- What is CORS?
- What is the difference between CORS and CSRF?
- What is session-based security?
- What is stateless security?
- What is JWT?
- What is a bearer token?
- How does JWT authentication work?
- What is
SessionCreationPolicy.STATELESS? - How should I configure Spring Security for REST APIs?
- What are common exam traps?
1. Quick Review from Week 6 Day 3
In Day 3, I learned:
- Authorization checks permissions.
- Authentication proves identity.
- Roles are authorities with
ROLE_prefix. hasRole("ADMIN")checksROLE_ADMIN.hasAuthority("TASK_READ")checks exactlyTASK_READ.- URL authorization protects endpoints.
- Method security protects methods.
@PreAuthorizechecks before method execution.- Data-level permissions belong in service/domain logic.
- Never trust client-sent user identity.
- Backend must enforce authorization.
Memory sentence:
Authentication = who are you?
Authorization = what can you do?
Today I learn how REST API security configuration changes depending on browser sessions, stateless APIs, CORS, CSRF, and JWT.
2. Big Picture
Spring Security can support different application styles.
Common styles:
1. Traditional web app with server-side pages
2. Browser app with session cookie
3. REST API with HTTP Basic
4. REST API with JWT bearer token
5. OAuth2 / OpenID Connect login
6. OAuth2 Resource Server
Important:
Security configuration depends on the application style.
A configuration that is correct for a stateless JWT API may be wrong for a browser session app.
Memory sentence:
Security configuration depends on how the client authenticates.
3. Session-Based Security
Session-based security means:
The server stores login state in an HTTP session.
Flow:
1. User logs in with username/password.
2. Server authenticates the user.
3. Server creates an HTTP session.
4. Browser receives a session cookie.
5. Browser sends the cookie on future requests.
6. Server uses the session to find the current user.
The session cookie is often:
JSESSIONID
Memory sentence:
Session security stores authentication state on the server.
4. Session-Based Flow
Example:
POST /login
Content-Type: application/x-www-form-urlencoded
username=user@example.com&password=password
If login succeeds, server returns:
Set-Cookie: JSESSIONID=abc123; HttpOnly; Secure
Later request:
GET /api/tasks
Cookie: JSESSIONID=abc123
Server uses the session ID to find the authentication.
Memory sentence:
In session security, the cookie points to server-side login state.
5. Stateless Security
Stateless security means:
The server does not store authentication state in an HTTP session.
Instead, the client sends credentials or a token with every request.
Example with bearer token:
GET /api/tasks
Authorization: Bearer eyJhbGciOi...
Flow:
1. Client sends token.
2. Server validates token.
3. Server creates Authentication for this request.
4. Request is authorized.
5. Server does not need an HTTP session for login state.
Memory sentence:
Stateless APIs authenticate each request independently.
6. Session vs Stateless
| Topic | Session-Based | Stateless Token |
|---|---|---|
| Login state | stored on server | stored/represented by token |
| Client sends | session cookie | bearer token |
| Common for | browser apps | REST APIs, mobile apps |
| Server memory | session storage | usually no session |
| CSRF concern | important with cookies | usually lower with Authorization header |
| Scaling | needs shared/session strategy | easier to scale |
Memory:
Session = server remembers.
Stateless = token proves each request.
7. What Is CSRF?
CSRF means:
Cross-Site Request Forgery
Simple definition:
CSRF is an attack where a malicious site tricks the user's browser into sending an authenticated request to another site.
Example:
User is logged in to bank.com.
Browser has bank.com session cookie.
User visits evil.com.
evil.com causes browser to send POST request to bank.com.
Browser automatically includes bank.com cookies.
The dangerous part:
Browser automatically sends cookies.
Memory sentence:
CSRF abuses automatic browser cookies.
8. CSRF Example
User is logged in to:
https://example-bank.com
Their browser has:
JSESSIONID=abc123
A malicious website contains:
<form action="https://example-bank.com/transfer" method="post">
<input name="amount" value="1000" />
<input name="to" value="attacker" />
</form>
<script>
document.forms[0].submit();
</script>
If the browser sends the bank session cookie automatically, the bank might think the request is legitimate.
CSRF protection prevents this by requiring a valid CSRF token.
Memory sentence:
CSRF protection proves the request came from the real application page, not another site.
9. Safe and Unsafe HTTP Methods
Safe methods should not change server state.
Usually safe:
GET
HEAD
OPTIONS
TRACE
Unsafe methods can change server state:
POST
PUT
PATCH
DELETE
CSRF protection mainly matters for unsafe methods.
Memory sentence:
CSRF protection matters most for state-changing requests.
10. CSRF in Spring Security
Spring Security enables CSRF protection by default in many servlet web applications.
This means unsafe requests may require a CSRF token.
Example test failure:
POST /api/tasks returns 403
Possible reason:
CSRF token is missing
Memory sentence:
With CSRF enabled, unsafe methods need a valid CSRF token.
11. When CSRF Should Usually Stay Enabled
CSRF is important when:
browser-based app
session cookie authentication
form login
server-rendered pages
cookies are automatically sent by browser
Example:
Thymeleaf app with login session
React app using cookie-based session
traditional Spring MVC web app
Memory sentence:
If authentication uses browser cookies, take CSRF seriously.
12. When CSRF Is Commonly Disabled
CSRF is commonly disabled for stateless REST APIs when:
API uses Authorization: Bearer token
API does not rely on cookies for authentication
server does not use HTTP session for authentication
client sends token manually in header
Example:
Authorization: Bearer eyJhbGciOi...
Reason:
Browser does not automatically attach custom Authorization bearer tokens to cross-site requests in the same way it automatically sends cookies.
Important:
Do not disable CSRF blindly.
Understand the authentication mechanism first.
Memory sentence:
CSRF is mainly a cookie/session problem, not usually a bearer-token-header problem.
13. CSRF Configuration
For a stateless REST API:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.build();
}
But for a browser session app, do not disable it blindly.
Memory sentence:
Disable CSRF only when the application style makes it appropriate.
14. Testing with CSRF
If CSRF is enabled, a test for POST needs CSRF token.
Example:
mockMvc.perform(post("/api/tasks")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"title":"Learn Security"}
"""))
.andExpect(status().isCreated());
Without .with(csrf()), the test may return:
403 Forbidden
Memory sentence:
In tests, POST/PUT/PATCH/DELETE may need
.with(csrf())if CSRF is enabled.
15. What Is CORS?
CORS means:
Cross-Origin Resource Sharing
CORS answers:
Which browser origins are allowed to call my API?
Example:
Frontend:
https://app.example.com
Backend API:
https://api.example.com
Different origins.
The browser asks:
Is https://app.example.com allowed to call https://api.example.com?
Memory sentence:
CORS controls which browser origins may call the API.
16. What Is an Origin?
An origin is:
scheme + host + port
Examples:
http://localhost:3000
http://localhost:8080
https://app.example.com
https://api.example.com
These are different origins:
http://localhost:3000
http://localhost:8080
because the port is different.
Memory sentence:
Origin means protocol, host, and port.
17. CORS Example
Frontend request:
GET https://api.example.com/api/tasks
Origin: https://app.example.com
If API allows it, response includes:
Access-Control-Allow-Origin: https://app.example.com
Then browser allows frontend JavaScript to read the response.
If not allowed, browser blocks the response.
Memory sentence:
CORS is enforced by the browser.
18. Preflight Request
For some cross-origin requests, the browser sends a preflight request first.
Example:
OPTIONS /api/tasks
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization, Content-Type
The server must respond with allowed methods/headers.
If preflight fails:
real request is not sent
Memory sentence:
Preflight is the browser asking permission before the real request.
19. Why CORS Must Work with Spring Security
CORS preflight requests usually do not include cookies or authentication.
If Spring Security requires authentication before CORS is processed, the preflight may be rejected.
That causes browser errors.
Memory sentence:
CORS must be configured so preflight requests are allowed correctly.
20. CORS vs CSRF
CORS and CSRF are different.
| Topic | CORS | CSRF |
|---|---|---|
| Main question | Which origins may call API? | Is this state-changing request forged? |
| Enforced by | browser | server-side protection |
| Common symptom | browser blocks response | server returns 403 |
| Related to | cross-origin JavaScript | automatic cookies |
| Example | React app calls API | malicious site submits form |
Memory sentence:
CORS controls who can call from browser.
CSRF protects against forged browser requests.
21. Common CORS Configuration
Configuration bean:
@Configuration
public class CorsConfig {
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://app.example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
Security config:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.build();
}
Memory sentence:
Define CORS configuration and enable
cors()in Spring Security.
22. CORS Development Example
Local frontend:
http://localhost:3000
Local backend:
http://localhost:8080
CORS config:
config.setAllowedOrigins(List.of("http://localhost:3000"));
Do not use broad wildcard settings in production without thinking.
Bad production habit:
config.setAllowedOrigins(List.of("*"));
Especially dangerous with credentials.
Memory sentence:
Allow only trusted frontend origins.
23. allowCredentials
allowCredentials(true) allows browser to include credentials such as cookies.
If using cookies/session:
config.setAllowCredentials(true);
But then you cannot safely use wildcard origin:
*
Use explicit origins.
Memory sentence:
Credentials plus wildcard origins are a dangerous combination.
24. Stateless REST API Security
A stateless REST API commonly uses:
Authorization: Bearer <token>
Configuration usually includes:
CSRF disabled
session creation policy stateless
JWT/resource server or custom token filter
public auth endpoints
protected API endpoints
CORS configured for frontend
Memory sentence:
Stateless REST APIs usually use bearer tokens and no server-side login session.
25. SessionCreationPolicy
Spring Security session policy controls session usage.
Common values:
ALWAYS
IF_REQUIRED
NEVER
STATELESS
Most important for REST APIs:
SessionCreationPolicy.STATELESS
Meaning:
Spring Security should not create or use HTTP session for security context.
Memory sentence:
STATELESSmeans do not use HTTP session for authentication state.
26. Stateless Configuration Example
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
)
.build();
}
This does not yet define JWT validation.
It only says:
no CSRF token requirement
no HTTP session for auth state
public auth and health endpoints
other endpoints require authentication
Memory sentence:
Stateless config needs an authentication mechanism, usually bearer token/JWT.
27. What Is JWT?
JWT means:
JSON Web Token
A JWT is a compact token string that can contain claims.
Example claims:
{
"sub": "user@example.com",
"userId": 10,
"tenantId": 5,
"roles": ["USER"],
"iat": 1720000000,
"exp": 1720003600
}
JWT is commonly sent as a bearer token:
Authorization: Bearer eyJhbGciOi...
Memory sentence:
JWT is a token format that carries claims.
28. JWT Structure
A JWT usually has three parts:
header.payload.signature
Example shape:
xxxxx.yyyyy.zzzzz
Header:
algorithm and token type
Payload:
claims such as subject, roles, expiry
Signature:
proves token was issued by trusted signer and was not modified
Memory sentence:
JWT has header, payload, and signature.
29. JWT Is Not Automatically Encrypted
Important:
JWT payload is usually Base64URL-encoded, not encrypted.
This means clients can often read the claims.
Do not put secrets inside JWT payload.
Bad:
{
"password": "secret123"
}
Good:
{
"sub": "user@example.com",
"roles": ["USER"],
"exp": 1720003600
}
Memory sentence:
JWT is signed, not necessarily encrypted.
30. Bearer Token
A bearer token means:
Whoever possesses the token can use it.
Header:
Authorization: Bearer <token>
Important:
Protect bearer tokens carefully.
Use HTTPS.
Do not log tokens.
Do not store them carelessly.
Memory sentence:
Bearer token means possession grants access.
31. JWT Login Flow
A common custom JWT login flow:
1. User sends email/password to POST /api/auth/login.
2. Server authenticates credentials using AuthenticationManager.
3. Server creates signed JWT.
4. Server returns JWT to client.
5. Client stores token.
6. Client sends Authorization: Bearer <jwt> on future requests.
7. Server validates JWT on every request.
8. If valid, server creates Authentication for the request.
Memory sentence:
Login creates token; future requests present token.
32. JWT Request Flow
Request:
GET /api/tasks
Authorization: Bearer eyJhbGciOi...
Flow:
1. Security filter reads Authorization header.
2. Token is extracted.
3. Token signature is verified.
4. Expiration is checked.
5. Claims are read.
6. Authorities are created from claims.
7. Authentication is stored in SecurityContext.
8. Authorization rules are checked.
9. Controller runs if allowed.
Memory sentence:
JWT validation turns a token into Authentication.
33. JWT and Logout
With sessions:
logout can invalidate server session
With stateless JWT:
server may not store token
logout is harder
Options:
short token expiration
refresh tokens
token blacklist/revocation list
change signing key
OAuth2 authorization server handles revocation
Memory sentence:
Stateless JWT makes logout/revocation harder than sessions.
34. JWT Expiration
JWT should have expiration.
Common claim:
exp
Why?
If token is stolen, it should not work forever.
Good design:
short-lived access token
optional refresh token
secure storage
rotation/revocation strategy
Memory sentence:
JWTs should expire.
35. Custom JWT Filter vs Resource Server
There are two common approaches.
Custom JWT Filter
You write your own filter:
read Authorization header
validate token
create Authentication
set SecurityContext
Good for learning, but easy to make mistakes.
OAuth2 Resource Server
Spring Security validates bearer JWTs using resource server support.
Example config:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults())
)
.build();
}
Memory sentence:
Prefer built-in resource server support when possible.
36. Resource Server Dependency
For OAuth2 Resource Server JWT support, common dependency:
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
Then configure issuer or JWK set URI.
Example:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://issuer.example.com
or:
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://issuer.example.com/.well-known/jwks.json
Memory sentence:
Resource server validates JWTs issued by a trusted authorization server.
37. JWT Authorities Mapping
JWT may contain roles/scopes.
Example payload:
{
"sub": "user@example.com",
"scope": "task:read task:write"
}
Spring Security can map scopes to authorities.
Common authority shape:
SCOPE_task:read
SCOPE_task:write
Then rule:
.requestMatchers(HttpMethod.GET, "/api/tasks/**")
.hasAuthority("SCOPE_task:read")
Memory sentence:
JWT claims must be mapped to Spring Security authorities.
38. Custom Claims Example
JWT payload:
{
"sub": "user@example.com",
"tenantId": 5,
"roles": ["ADMIN"]
}
Spring Security needs to convert this into authorities like:
ROLE_ADMIN
and maybe custom principal/claims access.
Important:
JWT claims do not automatically become your exact roles unless configured.
Memory sentence:
Token claims are not useful until Spring maps them to Authentication and authorities.
39. Where to Store JWT on Client
Common options:
memory
secure HTTP-only cookie
browser storage
mobile secure storage
Each has trade-offs.
Important:
LocalStorage is vulnerable if XSS happens.
Cookies can bring CSRF concerns if used for authentication.
Authorization header avoids automatic cookie sending.
Memory sentence:
Token storage choice affects security risks.
40. REST API Security Config Example
Example for stateless JWT resource server:
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers(HttpMethod.GET, "/api/tasks/**")
.hasAuthority("SCOPE_task:read")
.requestMatchers(HttpMethod.POST, "/api/tasks/**")
.hasAuthority("SCOPE_task:write")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults())
)
.build();
}
}
This config means:
CORS enabled
CSRF disabled for stateless API
no HTTP session for auth state
auth and health are public
task read/write require authorities
JWT bearer token authentication enabled
method security enabled
41. REST API with Custom Login + JWT
A custom login endpoint may be public:
.requestMatchers("/api/auth/login").permitAll()
Login controller:
@PostMapping("/api/auth/login")
public TokenResponse login(@Valid @RequestBody LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.email(),
request.password()
)
);
String token = jwtService.createToken(authentication);
return new TokenResponse(token);
}
Future requests:
Authorization: Bearer <token>
Important:
Login authenticates credentials.
JWT authenticates future requests.
Memory sentence:
Custom login uses AuthenticationManager; protected endpoints use bearer token.
42. Common REST API Endpoint Rules
Typical public endpoints:
POST /api/auth/login
POST /api/auth/register
GET /actuator/health
GET /api/public/**
Typical protected endpoints:
/api/tasks/**
/api/clients/**
/api/users/me
/api/documents/**
Admin endpoints:
/api/admin/**
Example:
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
Memory sentence:
Keep public endpoints explicit and protect everything else.
43. Default Deny Mindset
A safe security mindset:
Open only what must be public.
Require authentication for everything else.
Add stronger rules for admin or sensitive endpoints.
Good:
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
Risky:
.anyRequest().permitAll()
Memory sentence:
Public by exception, protected by default.
44. Common REST API Mistakes
Mistake 1:
Disabling CSRF without understanding authentication style.
Mistake 2:
Not configuring CORS for frontend origin.
Mistake 3:
Using sessions accidentally in a JWT API.
Mistake 4:
Returning tokens in logs.
Mistake 5:
Putting secrets in JWT claims.
Mistake 6:
Trusting JWT claims without verifying signature.
Mistake 7:
No token expiration.
Mistake 8:
Using wildcard CORS origins in production.
Mistake 9:
Using frontend authorization only.
Mistake 10:
Not mapping JWT claims to authorities correctly.
45. Security Headers Short Note
Spring Security also helps with HTTP security headers.
Examples:
X-Content-Type-Options
Cache-Control
X-Frame-Options
Strict-Transport-Security
Content-Security-Policy
Do not disable headers blindly.
Memory sentence:
Security is more than login; headers also protect the browser.
46. HTTPS Is Required
For real applications:
Use HTTPS.
Why?
protects passwords
protects tokens
protects cookies
prevents many network attacks
Without HTTPS, bearer tokens and Basic credentials can be stolen.
Memory sentence:
No HTTPS means no real transport security.
47. Common Exam Traps
Trap 1
CSRF and CORS are different.
Trap 2
CSRF protects against forged state-changing browser requests.
Trap 3
CORS controls which browser origins may access the API.
Trap 4
CSRF matters especially with browser cookies and sessions.
Trap 5
Stateless bearer-token APIs commonly disable CSRF, but not blindly.
Trap 6
CORS preflight uses OPTIONS and often has no authentication cookies.
Trap 7
Session security stores authentication state on the server.
Trap 8
Stateless security authenticates each request independently.
Trap 9
SessionCreationPolicy.STATELESS means no HTTP session for security context.
Trap 10
JWT is signed, not necessarily encrypted.
Trap 11
Do not put secrets in JWT payload.
Trap 12
Bearer token means whoever has the token can use it.
Trap 13
JWT should expire.
Trap 14
JWT claims must be mapped to authorities.
Trap 15
Use HTTPS for credentials, cookies, and tokens.
48. Real Exam Question: CSRF
Question:
What is CSRF?
Answer:
CSRF is an attack where a malicious site tricks a user’s browser into sending an authenticated state-changing request to another site, often using automatically sent cookies.
49. Real Exam Question: CORS
Question:
What is CORS?
Answer:
CORS is a browser security mechanism that controls which origins are allowed to make cross-origin requests to a server.
50. Real Exam Question: CORS vs CSRF
Question:
What is the difference between CORS and CSRF?
Answer:
CORS controls which browser origins may call an API. CSRF protects against forged authenticated browser requests, especially when cookies are automatically sent.
51. Real Exam Question: Session Security
Question:
What is session-based security?
Answer:
Session-based security stores authentication state on the server in an HTTP session and uses a session cookie to identify the user on future requests.
52. Real Exam Question: Stateless Security
Question:
What is stateless security?
Answer:
Stateless security means the server does not store authentication state in an HTTP session. The client sends credentials or a token with every request.
53. Real Exam Question: JWT
Question:
What is JWT?
Answer:
JWT means JSON Web Token. It is a compact token format that can carry claims and is usually signed so the server can verify it was not modified.
54. Real Exam Question: Bearer Token
Question:
What is a bearer token?
Answer:
A bearer token is a token where possession grants access. The client usually sends it in the Authorization: Bearer <token> header.
55. Real Exam Question: Stateless Session Policy
Question:
What does SessionCreationPolicy.STATELESS mean?
Answer:
It tells Spring Security not to create or use an HTTP session for storing the security context.
56. Real Exam Question: JWT Encryption
Question:
Is JWT payload always encrypted?
Answer:
No. A JWT payload is often only encoded and signed, not encrypted. Do not put secrets in JWT claims.
57. Interview Answer
Question:
Explain CSRF and when you would disable it.
Good answer:
CSRF is an attack where a malicious website causes the browser to send an authenticated state-changing request to another site, usually relying on cookies that the browser sends automatically. I keep CSRF protection for browser apps using sessions or cookies. For stateless REST APIs using bearer tokens in the Authorization header and not relying on cookies for authentication, CSRF is commonly disabled, but I do not disable it blindly.
58. Interview Answer
Question:
Explain CORS.
Good answer:
CORS controls which browser origins are allowed to call an API. It is enforced by the browser. For example, if a React app on http://localhost:3000 calls a Spring Boot API on http://localhost:8080, the backend must allow that origin. For non-simple requests, the browser sends a preflight OPTIONS request first, and the server must allow the requested method and headers.
59. Interview Answer
Question:
What is the difference between session-based and stateless authentication?
Good answer:
In session-based authentication, the server stores the authentication state in an HTTP session and the browser sends a session cookie. In stateless authentication, the server does not store login state in a session. The client sends a token, such as a JWT bearer token, with every request, and the server validates it each time.
60. Interview Answer
Question:
Explain JWT authentication flow.
Good answer:
A user first logs in with username and password. The server authenticates the credentials, usually with AuthenticationManager. If login succeeds, the server creates a signed JWT and returns it to the client. On future requests, the client sends Authorization: Bearer <token>. Spring Security validates the token, reads claims, creates an Authentication, stores it in the SecurityContext, and then applies authorization rules.
61. Interview Answer
Question:
What are common mistakes with JWT APIs?
Good answer:
Common mistakes include not using HTTPS, storing sensitive data in JWT claims, using tokens without expiration, logging tokens, not validating the signature, not mapping claims to authorities correctly, accidentally using sessions, and using unsafe CORS settings like allowing every origin in production.
62. Tiny Code Practice
Security config:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults())
)
.build();
}
Questions:
- Is CSRF enabled or disabled?
- Does this use HTTP session for auth state?
- Which endpoints are public?
- What authentication style is used for protected endpoints?
- What does
anyRequest().authenticated()mean?
Answers:
- Disabled.
- No, it uses
STATELESS. /api/auth/**and/actuator/health.- JWT bearer token resource server.
- Every other request requires authentication.
63. Tiny Bug Practice 1
Problem:
.csrf(csrf -> csrf.disable())
Question:
Is this always correct?
Answer:
No. It is common for stateless bearer-token REST APIs, but it can be wrong for browser apps using session cookies. CSRF should not be disabled blindly.
64. Tiny Bug Practice 2
Problem:
Frontend:
http://localhost:3000
Backend:
http://localhost:8080
Browser error:
CORS policy blocked the request
Question:
What is likely missing?
Answer:
The backend probably does not allow the frontend origin. Configure CORS to allow http://localhost:3000 and enable CORS in Spring Security.
65. Tiny Bug Practice 3
Problem:
JWT payload:
{
"sub": "user@example.com",
"password": "secret123"
}
Question:
What is wrong?
Answer:
JWT payload is not necessarily encrypted and can often be read by the client. Never put passwords or secrets in JWT claims.
66. Tiny Bug Practice 4
Problem:
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().permitAll()
Question:
What is risky?
Answer:
Everything not matching /api/admin/** is public. For APIs, it is usually safer to make only specific endpoints public and require authentication for everything else.
Better:
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
Practice Questions and Answers
Question 1
What is CSRF?
Answer:
CSRF is an attack where a malicious site tricks a user’s browser into sending an authenticated state-changing request to another site.
Question 2
Why does CSRF matter especially with cookies?
Answer:
Because browsers automatically send cookies, including session cookies, with requests to the cookie’s site.
Question 3
When is CSRF commonly disabled?
Answer:
CSRF is commonly disabled for stateless REST APIs that use bearer tokens in the Authorization header and do not rely on cookies for authentication.
Question 4
What is CORS?
Answer:
CORS is a browser mechanism that controls which origins are allowed to make cross-origin requests to an API.
Question 5
What is an origin?
Answer:
An origin is the combination of scheme, host, and port.
Question 6
What is a CORS preflight request?
Answer:
A preflight request is an OPTIONS request sent by the browser before the real cross-origin request to check whether the method and headers are allowed.
Question 7
What is the difference between CORS and CSRF?
Answer:
CORS controls which browser origins may access the API. CSRF protects against forged authenticated browser requests.
Question 8
What is session-based security?
Answer:
Session-based security stores authentication state on the server and uses a session cookie.
Question 9
What is stateless security?
Answer:
Stateless security does not store authentication state in an HTTP session. The client sends a token or credentials with every request.
Question 10
What does SessionCreationPolicy.STATELESS mean?
Answer:
It means Spring Security should not create or use an HTTP session for storing authentication state.
Question 11
What is JWT?
Answer:
JWT means JSON Web Token. It is a compact token format that can carry claims and is usually signed.
Question 12
What are the three parts of a JWT?
Answer:
Header, payload, and signature.
Question 13
Is JWT always encrypted?
Answer:
No. JWT is usually signed but not necessarily encrypted.
Question 14
What is a bearer token?
Answer:
A bearer token is a token where whoever possesses it can use it to access protected resources.
Question 15
Why should JWTs expire?
Answer:
Because if a token is stolen, expiration limits how long it can be used.
Question 16
What does OAuth2 Resource Server support do?
Answer:
It lets Spring Security protect endpoints by validating OAuth2 bearer tokens such as JWTs.
Question 17
What is the difference between login request and future JWT requests?
Answer:
The login request authenticates username/password and creates a token. Future requests use the token in the Authorization header.
Question 18
Why should I not log tokens?
Answer:
Because tokens can grant access. If logs leak, attackers may use the token.
Question 19
Why is HTTPS required?
Answer:
HTTPS protects credentials, cookies, and tokens during transport.
Question 20
What is a safe default mindset for endpoint security?
Answer:
Open only what must be public. Require authentication for everything else. Add stronger rules for admin or sensitive endpoints.
Final Memory Sentences
- CSRF means Cross-Site Request Forgery.
- CSRF abuses automatic browser cookies.
- CSRF matters especially with session/cookie authentication.
- Stateless bearer-token APIs commonly disable CSRF, but not blindly.
- CORS means Cross-Origin Resource Sharing.
- Origin means scheme, host, and port.
- CORS controls which browser origins may call the API.
- Preflight is an OPTIONS permission check.
- CORS and CSRF are different.
- Session security stores authentication state on the server.
- Stateless security authenticates every request independently.
SessionCreationPolicy.STATELESSmeans no HTTP session for auth state.- JWT means JSON Web Token.
- JWT has header, payload, and signature.
- JWT is signed, not necessarily encrypted.
- Do not put secrets in JWT claims.
- Bearer token means possession grants access.
- JWTs should expire.
- Login creates token; future requests present token.
- JWT validation creates Authentication.
- JWT claims must be mapped to authorities.
- Use HTTPS for real applications.
- Public by exception, protected by default.