Episode ini membahas autentikasi modern: peran OAuth 2.0 authorization server vs resource server, implementasi token- based auth dengan JWT, integrasi identity provider eksternal seperti Keycloak, serta best practice refresh token, token revocation, dan scopes.

Basic auth dengan username dan password mentah tidak cukup untuk aplikasi modern — apalagi ketika kalian harus berintegrasi dengan login pihak ketiga seperti Google, GitHub, atau perusahaan lain. Episode 13 membawa keamanan kalian ke tingkat berikutnya dengan OAuth 2.0 dan JWT.
Kalian akan memahami pembagian peran dalam OAuth 2.0, membangun resource server yang memvalidasi token JWT, mengintegrasikan identity provider eksternal, dan menerapkan best practice untuk refresh token serta scopes.
OAuth 2.0 memisahkan tanggung jawab keamanan ke beberapa peran:
Peran aplikasi kalian menentukan konfigurasi Spring. Sebagian besar aplikasi backend adalah resource server: mereka tidak menerbitkan token, hanya memvalidasi.
Pemahaman grant type membantu memilih alur yang tepat. Untuk service internal, client_credentials cukup; untuk aplikasi dengan user, gunakan authorization_code.
Spring Security menyediakan dukungan JWT out-of-the-box:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>Resource server memvalidasi setiap token dengan kunci yang dibagikan. Konfigurasi memakai JWK Set URI dari authorization server:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:8081/realms/belajar
jwk-set-uri: http://localhost:8081/realms/belajar/protocol/openid-connect/certsSpring memuat kunci publik dari jwk-set-uri dan memvalidasi signature serta klaim token secara otomatis. Ini menghilangkan kebutuhan menulis parser JWT sendiri.
Kontrol akses berdasarkan klaim yang ada di token — misalnya peran atau scope:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
return http
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults()))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/admin/**")
.hasAuthority("SCOPE_admin")
.requestMatchers("/api/items/**")
.hasAuthority("SCOPE_read")
.anyRequest().authenticated())
.build();
}Klaim scope dari token JWT dipetakan menjadi authority dengan prefix SCOPE_. Dengan pola ini, kendali akses berpindah ke isi token — resource server tidak perlu menyimpan sesi. Uji endpoint dengan token: curl -H 'Authorization: Bearer <token>' http://localhost:8080/api/items mengirim JWT lewat header Authorization.
Untuk development tanpa authorization server eksternal, kalian bisa menerbitkan token sendiri dengan jjwt:
SecretKey key = Keys.hmacShaKeyFor(secret.getBytes());
String token = Jwts.builder()
.subject("arman")
.claim("scope", List.of("read", "admin"))
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(key, Jwts.SIG.HS256)
.compact();Contoh di atas memakai jjwt untuk membuat token dengan klaim scope. Dalam produksi, penerbitan token tetap di authorization server — kode ini hanya untuk eksperimen dan testing.
Daripada membangun login sendiri, banyak tim memakai identity provider seperti Keycloak (self-hosted), Okta, atau Auth0. Spring Boot mengintegrasikan mereka lewat alur authorization code dengan Spring Security OAuth2 Client:
spring:
security:
oauth2:
client:
registration:
keycloak:
client-id: belajar-app
client-secret: rahasia
scope: openid, profile, email
authorization-grant-type: authorization_code
provider:
keycloak:
issuer-uri: http://localhost:8081/realms/belajarTambahkan dependency spring-boot-starter-oauth2-client dan Spring menyediakan halaman login, callback, dan pengelolaan sesi secara otomatis. User yang masuk bisa diakses lewat OAuth2User di controller.
Access token berumur pendek — biasanya 5-15 menit — sedangkan refresh token berumur lebih panjang dan dipakai untuk mendapatkan access token baru tanpa login ulang. Simpan access token di memory; jangan simpan refresh token di browser untuk aplikasi berbasis cookie.
Login -> access token (15 menit) + refresh token (7 hari)
Access token habis -> tukar refresh token -> access token baruSaat user logout atau token dicurigai, token harus bisa dicabut. Keycloak menyediakan endpoint revocation, dan refresh token bisa di-revoke sehingga akses berhenti. Batasi juga scope seminimal mungkin — jangan minta admin jika aplikasi hanya butuh read. Prinsip least privilege mengurangi risiko saat token bocor.
Episode 13 membekali kalian dengan autentikasi modern: memahami peran authorization server dan resource server dalam OAuth 2.0, membangun resource server yang memvalidasi JWT, mengintegrasikan identity provider eksternal, serta menerapkan best practice untuk refresh token, revocation, dan scopes.
Inti yang harus dibawa pulang:
spring-boot-starter-oauth2-resource-server memvalidasi JWT via JWK Set URI.scope di token dipetakan menjadi authority SCOPE_....Di episode 14 selanjutnya kita akan membahas API gateway dan secure microservices — pola API gateway sebagai boundary, Spring Cloud Gateway, autentikasi dan otorisasi service-to-service, serta rate limiting dan secure API contracts.