This episode covers modern security patterns in Java: an introduction to OAuth 2.0 and OpenID Connect, integration with Spring Security and Jakarta Security, secure headers, CORS, CSRF, mitigation of common attacks, and managing credentials and secrets in production environments.

Episode 13 built the cryptography foundation; episode 14 takes you to the modern security patterns and access control used by enterprise applications. You will learn OAuth 2.0 and OpenID Connect, integrate Spring Security, understand secure headers, CORS, and CSRF, and manage secrets in production.
Modern application security is not just encryption — it is about managing identity, controlling access rights, and protecting applications from ever-evolving attacks. This episode gives you the complete map.
OAuth 2.0 is the authorization standard that lets an application access resources on behalf of a user without sharing credentials. The basic flow: the client requests a token from the authorization server, then uses that token to access the resource server.
OpenID Connect (OIDC) is built on top of OAuth 2.0 and adds an authentication layer. It introduces the ID token that carries the user's identity. In the Java ecosystem, popular OIDC providers such as Keycloak and Okta are often used.
klien -> minta otorisasi -> server otorisasi -> access + ID token -> akses resourceSpring Security is the de facto security standard for Spring Boot. Add the dependency:
mvn dependency:get -Dartifact=org.springframework.boot:spring-boot-starter-security:3.3.2A simple configuration for validating JWTs from the authorization server:
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(rs -> rs.jwt());
return http.build();
}
}oauth2ResourceServer(rs -> rs.jwt()) makes the application validate JWTs on every protected request.
For Jakarta EE environments, use Jakarta Security with annotations:
import jakarta.annotation.security.RolesAllowed;
@RolesAllowed({"ADMIN", "USER"})
public class LayananData {
public String ambilData() {
return "data sensitif";
}
}@RolesAllowed({...}) restricts method access based on the user's role.
Security headers protect applications from browser-based attacks. Spring Security adds many headers by default: X-Content-Type-Options, X-Frame-Options, and Strict-Transport-Security. They can also be added manually:
http.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives(
"default-src 'self'; frame-ancestors 'none'")));CORS (Cross-Origin Resource Sharing) determines which origins are allowed to access the API. Configure the origin whitelist:
http.cors(cors -> cors.configurationSource(request -> {
var config = new org.springframework.web.cors.CorsConfiguration();
config.setAllowedOrigins(java.util.List.of("https://app.example.com"));
config.setAllowedMethods(java.util.List.of("GET", "POST", "PUT", "DELETE"));
return config;
}));CSRF (Cross-Site Request Forgery) is prevented with a CSRF token — enabled by default for session-based applications. For stateless APIs, CSRF is often disabled because there is no session. Other common attacks that must be mitigated: SQL injection with prepared statements, XSS with output escaping, and brute force with rate limiting.
Credentials such as the OAuth client secret and database passwords must not be in source code. Use environment variables as discussed in episode 11:
export CLIENT_ID="aplikasi-web"
export CLIENT_SECRET="rahasia-sangat-sensitif"In production environments, use a secret manager: HashiCorp Vault, AWS Secrets Manager, or the secret features of your cloud platform. The application reads secrets at runtime, so the code stays clean and secrets can be rotated without redeploying.
Info
Make sure secrets are rotated periodically, use the principle of least privilege, and give secret manager access only to the services that truly need it.
Episode 14 covers modern security patterns: OAuth 2.0 and OpenID Connect for authorization and authentication, Spring Security and Jakarta Security for application protection, secure headers, CORS, CSRF, mitigation of common attacks, and managing credentials and secrets in production.
Key takeaways:
@RolesAllowed.In the next episode, episode 15, we will discuss concurrency and parallelism — basic threads, runnable, and thread lifecycle, ExecutorService, thread pools, and task scheduling, synchronization, locks, atomic variables, and concurrent collections, plus the Java Flow API, reactive streams, and the java.util.concurrent structure. Time to leverage the multi-core!