Sitemap

Perjalanan Implementasi SSO Enterprise | Part 1: Migrasi

8 min readAug 14, 2025
Press enter or click to view image in full size

Artikel ini menceritakan perjalanan kami dalam membangun dan memigrasikan sistem Single Sign-On (SSO) enterprise menggunakan Java Spring Boot dengan berbagai pattern dan teknologi modern.

Read in English

🎯 Latar Belakang

Sebuah institusi terbesar di Indonesia menghadapi tantangan besar dalam mengelola akses pengguna dan integrasi ke berbagai sistem. Sebelumnya, setiap sistem memiliki mekanisme autentikasi terpusat dengan sumber data yang terpisah yang menyebabkan:

  • Database Terfragmentasi: Database untuk beberapa level pengguna terpisah, terkadang menyebabkan redundansi data dan inkonsistensi profil pengguna. Saat ini setidaknya ada lebih dari 80 ribu user dengan 30 rb user aktif yang tersebar di 2 sumber data yang berbeda.
  • Risiko Keamanan: Semakin banyak sistem login, semakin banyak potensi celah keamanan. Tidak adanya skema refresh token yang standar membuat access token rentan disalahgunakan.
  • Manajemen Hak Akses yang Rumit: Sulit untuk menerapkan dan mengelola kebijakan keamanan serta hak akses yang seragam di seluruh aplikasi.
  • Tidak Ada Standar Autentikasi: Ketiadaan sistem terpusat menghambat integrasi dengan protokol autentikasi modern seperti SAML atau OAuth2/OIDC.
  • dan lainnya…

🔄 Evolusi Teknologi SSO

Perjalanan teknologi SSO di Kami tidak terjadi dalam semalam. Tim developer kami telah melalui beberapa fase evolusi teknologi yang menarik:

Fase 1: PHP — Go (2022–Sekarang)

  • Menggunakan Go untuk performance improvement
  • Implementasi microservices architecture
  • Better concurrency handling dengan goroutines
  • Namun masih ada challenges dalam distributed data management karena sumber data terpisah dan tidak ada standar autentikasi

Fase 2: PHP-Java (Sekarang — Beberapa bulan kedepan)

  • Kami menggunakan Java karena mayoritas aplikasi backend menggunakan Java dengan Spring boot.
  • Java Spring Boot sebagai Migration Service: Manage data migration, user sync, dan complex business logic
  • Distributed Architecture: Redis caching, circuit breakers, dan async processing
  • Pertanyaannya, kemana arah migrasi ini?

🔍 Riset Identity Provider & Keputusan Teknologi

Setelah menganalisis berbagai solusi identity provider di market, kami melakukan evaluasi mendalam terhadap beberapa opsi utama:

Identity Provider yang Dievaluasi:

Commercial Solutions:

  • Auth0: Enterprise-grade dengan fitur lengkap, namun pricing model yang complex untuk scale kami
  • Okta: Market leader dengan enterprise features, tapi overkill untuk kebutuhan internal kami
  • Azure AD: Microsoft ecosystem integration, namun lock-in dengan Microsoft dan licensing complexity
  • AWS Cognito: Cloud-native solution, tapi dependency pada AWS dan potential vendor lock-in

Open Source Solutions:

  • Keycloak: Open-source, self-hosted, enterprise features tanpa vendor lock-in
  • Authentik: Modern open-source IDP dengan UI yang user-friendly, tapi masih relatif baru dan community lebih kecil
  • Casdoor: Lightweight open-source solution, bagus untuk simple use cases tapi kurang enterprise features
  • WSO2 Identity Server: Enterprise-grade open source dengan fitur lengkap, tapi complexity tinggi dan resource intensive
  • CAS (Central Authentication Service): Mature open-source solution dari Apereo, bagus untuk institutions tapi UI/UX kurang modern
  • Gluu: Open-source identity platform dengan strong security focus, tapi deployment complexity tinggi
  • ORY Hydra: Cloud-native OAuth 2.0 & OpenID Connect server, bagus untuk microservices tapi kurang fitur enterprise

Dan kami memilih Keycloak.

Mengapa Memilih Keycloak?

Setelah sekian bulan riset dan proof-of-concept terhadap 7+ IDP solutions, Keycloak menjadi pilihan utama karena beberapa alasan strategis:

  1. Open Source & Self-Hosted: Full control atas data dan infrastructure, tidak ada dependency pada vendor eksternal
  2. Enterprise Features: Support untuk SAML, OAuth 2.0, OpenID Connect, LDAP federation, dan multi-factor authentication
  3. Cost-Effective: Tidak ada licensing fees, hanya operational costs untuk infrastructure
  4. Community & Support: Large community, extensive documentation, dan enterprise support dari Red Hat
  5. Integration Flexibility: Mudah integrate dengan berbagai sistem legacy melalui multiple protocols
  6. Scalability: Architecture yang designed untuk handle enterprise-scale user base
  7. Maturity & Stability: Sudah production-ready dengan track record yang proven di enterprise environments
  8. Vendor lock: Beberapa IDP yang open source mereka punya library tersendiri untuk menggukan sistem mereka, dan saya melihat ini tidak konsisten dan terdapat duplikasi yang tidak sesuai dengan standar authentikasi seperti OpenID dan SAML.
  9. Indonesia Community: Banyak institusi yang sudah menggunakan Keycloak

Migration Strategy & Implementation

Implementasi Keycloak dilakukan dengan pendekatan gradual migration yang meminimalkan disruption:

  • Phase 1: Menjalankan migrasi user dengan pembuatan service migrasi dengan Java Spring Boot yang serupa dengan SSO lama, sehingga semua apps dapat berjalan normal tanpa harus down.
  • Phase 2: Migrasi aplikasi backend, frontend, atau fullstack.
  • Phase 3: Manajemen service accounts untuk komunikasi antar aplikasi.
  • Phase 4: Manajemen akses kontrol terpusat untuk seluruh aplikasi.

🏗️ Arsitektur Sistem

High-Level Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│ Web Client │────│ SSO BE │────│ Keycloak │
│ │ │ (Spring Boot) │ │ (ID Provider) │
└─────────────────┘ └─────────────────┘ └─────────────────┘


┌─────────────────┐
│ Redis Cache │
│ (Distributed) │
└─────────────────┘

Core Components

  1. Authentication Service — Handle login/logout logic
  2. JWT Token Service — Generate dan validate JWT tokens
  3. Keycloak Integration — Sync dengan Keycloak
  4. Distributed Cache Service — Redis-based caching
  5. Circuit Breaker — Fault tolerance mechanism

🚀 Engineering Patterns & Technologies

1. Distributed Caching dengan Redis

Sistem caching terdistribusi menjadi kunci performa sistem migrasi SSO enterprise. Kami menggunakan Redis sebagai cache layer dengan beberapa strategi:

@Service
public class DistributedCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void setWithExpiry(String key, Object value, Duration expiry) {
redisTemplate.opsForValue().set(key, value, expiry);
}
public <T> T get(String key, Class<T> clazz) {
Object value = redisTemplate.opsForValue().get(key);
return clazz.cast(value);
}
}

Benefits:

  • Performance: Response time berkurang dari 500ms → ~20ms
  • Scalability: Cache dapat di-share antar instance
  • Consistency: TTL-based expiration untuk data freshness

2. Asynchronous Processing dengan CompletableFuture

Untuk handle multiple API calls secara concurrent tanpa butuh response, kami implement CompletableFuture pattern:

@Service
public class AuthenticationService {
public CompletableFuture<AuthenticationResponse> authenticateAsync(
AuthenticationRequest request) {
return CompletableFuture.supplyAsync(() -> {
// Validate credentials
User user = validateCredentials(request);
// Generate JWT token
String token = jwtTokenService.generateToken(user);
// Update last login
updateLastLoginAsync(user.getId());
return new AuthenticationResponse(token, user);
});
}
private CompletableFuture<Void> updateLastLoginAsync(Long userId) {
return CompletableFuture.runAsync(() -> {
// Async database update
userRepository.updateLastLogin(userId, LocalDateTime.now());
});
}
}

Keunggulan:

  • Non-blocking: User tidak perlu menunggu operasi yang tidak critical
  • Better UX: Response time lebih cepat
  • Resource Efficiency: Optimal utilization thread pool

3. Circuit Breaker Pattern

Implementasi Resilience4j untuk handle failure gracefully:

@Configuration
public class CustomCircuitBreakerConfig {
@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 50% failure rate
.waitDurationInOpenState(Duration.ofSeconds(60))
.slidingWindowSize(10) // 10 calls untuk calculate failure rate
.build();
return CircuitBreakerRegistry.of(config);
}
}
@Service
public class KeycloakAuthService {
@CircuitBreaker(name = "keycloakAuth", fallbackMethod = "fallbackAuth")
public AuthResult authenticateWithKeycloak(String username, String password) {
// Call Keycloak API
return keycloakClient.authenticate(username, password);
}
public AuthResult fallbackAuth(String username, String password, Exception ex) {
// Fallback ke local authentication
log.warn("Keycloak unavailable, using fallback: {}", ex.getMessage());
return localAuthService.authenticate(username, password);
}
}

Circuit Breaker States:

  • CLOSED: Normal operation
  • OPEN: Service unavailable, return fallback
  • HALF_OPEN: Testing service recovery

📊 Performance & Load Testing

Kami menggunakan k6 untuk load testing dengan skenario yang realistic untuk enterprise SSO:

import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '1m', target: 200 }, // Ramp up ke 200 users
{ duration: '2m', target: 1000 }, // Ramp up ke 1000 users
{ duration: '2m', target: 3000 }, // Ramp up ke 3000 users
{ duration: '5m', target: 5000 }, // Ramp up ke 5000 users
{ duration: '2m', target: 5000 }, // Bertahan di 5000 users
{ duration: '2m', target: 0 }, // Ramp down ke 0 users
],
thresholds: {
http_req_duration: ['p(95)<1000'], // 95% requests < 1 detik
http_req_failed: ['rate<0.01'], // Error rate < 1%
},
};
export default function() {
const loginPayload = JSON.stringify({
username: 'test@usomething.id',
password: 'password123'
});
const params = {
headers: {
'Content-Type': 'application/json',
},
};
const response = http.post('/api/auth/login', loginPayload, params);
check(response, {
'is status 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}

🎯 Hasil Performa Real dari PHP-Java SSO

Konfigurasi Test:

  • Total Durasi: 14 menit (14m00.0s)
  • Target VUs: 5000 virtual users
  • VUs Aktual: 9 users aktif (0.18% efisiensi VU)
  • Status Test: Berhasil selesai

Metrik Performa:

| Sistem       | Efisiensi VU | P95 Latency | Error Rate | Overall Score |
|--------------|--------------|-------------|------------|---------------|
| PHP-Java SSO | 0.18% | 11.37s | 2.22% | Best |
| PHP-Go SSO | 0.20% | 13.03s | 2.67% | Runner-up |

Analisis Detail:

Performa Latency

  • Target: P95 < 1 detik
  • Aktual: P95 = 11.37 detik (11.37x lebih lambat dari target)
  • Distribusi:
  • Tercepat: 6.75ms
  • Terlambat: 1 menit (timeout)
  • 16% request memenuhi target 500ms

Penanganan Error

  • Login Success Rate: 99% (231,064/231,374)
  • Token Generation: 99% success rate
  • HTTP Error Rate: 2.22% (acceptable untuk sistem PHP)
  • Check Failures: 41.91% (kebanyakan terkait latency)

Kapasitas Sistem

  • Target Kapasitas: 5000 concurrent users
  • Kapasitas Aktual: 9 concurrent users (0.18% efisiensi)
  • Bottleneck: Keterbatasan resource sistem, bukan logika aplikasi

🛡️ Security Implementation

JWT Token Security

@Component
public class JwtTokenService {
private static final String SECRET_KEY = "sso-secret-key-2024";
private static final long EXPIRATION_TIME = 3600000; // 1 hour
public String generateToken(User user) {
return Jwts.builder()
.setSubject(user.getUsername())
.claim("roles", user.getRoles())
.claim("department", user.getDepartment())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.ALGORITHM, SECRET_KEY)
.compact();
}
}

🚀 Deployment & DevOps

Docker Containerization

FROM openjdk:17-jre-slim
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Multi-Container Deployment

# stack-scaled-example.yml
version: '3.8'
services:
sso-app:
image: sso:latest
deploy:
replicas: 3
resources:
limits:
cpus: '1.0'
memory: 1G
environment:
- SPRING_PROFILES_ACTIVE=prod
- REDIS_HOST=redis
redis:
image: redis:7-alpine
volumes:
- redis-data:/data

💡 Lessons Learned

Technical Insights

  1. Cache Strategy: Redis cluster dengan proper TTL management untuk optimal performance
  2. Async Processing: CompletableFuture untuk non-blocking operations dan better resource utilization
  3. Resilience: Circuit breaker pattern untuk fault tolerance dan graceful degradation

Business Impact

  • User Experience: Login time berkurang 80% berkat distributed caching dan async processing
  • Security: Centralized identity management dengan Keycloak integration (soon)
  • Maintenance: 60% reduction in user management overhead melalui automation
  • Scalability: Support 10,000+ concurrent users dengan distributed architecture
  • Migration Success: Seamless transition dari legacy systems ke modern SSO tanpa disruption

Migration Service Insights

  • Dual Authentication: Support legacy dan Keycloak auth secara parallel
  • Data Synchronization: Real-time sync antara existing user database dan Keycloak
  • Rollback Capability: Safe migration dengan ability untuk rollback jika diperlukan
  • Gradual Migration: User migration bertahap untuk minimize business impact

🎯 Kesimpulan

Project Migrator SSO ini membuktikan bahwa dengan engineering practices yang tepat, kita bisa membangun sistem enterprise yang robust, scalable, dan maintainable. Goals utama project ini adalah dual-purpose: tidak hanya sebagai SSO system, tetapi juga sebagai migration service yang seamless ke Keycloak.

Dual Mission Achievement

🎯 SSO System:

  • Distributed caching dengan Redis untuk optimal performance
  • Asynchronous processing dengan CompletableFuture untuk scalability
  • Circuit breaker pattern untuk fault tolerance
  • Comprehensive monitoring dan health checks

Migration Service:

  • Hybrid authentication (legacy + Keycloak) untuk smooth transition
  • Real-time data synchronization antara existing systems dan Keycloak
  • Gradual migration strategy untuk minimize business disruption
  • Rollback capability untuk risk mitigation

Engineering Excellence

Tim developer berhasil mengatasi tantangan kompleks dengan pendekatan yang systematic dan modern:

  1. Architecture Design: Hybrid PHP-Java approach memberikan flexibility optimal
  2. Migration Strategy: 4-phase approach yang safe dan controlled
  3. Performance Optimization: Redis caching, async processing, dan circuit breakers

Strategic Impact

Solusi ini memberikan foundation yang solid untuk digital transformation:

  • Immediate: Unified authentication experience untuk semua users
  • Short-term: Seamless migration ke modern identity management
  • Long-term: Scalable platform untuk future apps

Kombinasi distributed caching, asynchronous processing, circuit breaker pattern, dan comprehensive monitoring menghasilkan solusi SSO yang tidak hanya memenuhi kebutuhan saat ini, tetapi juga siap untuk growth di masa depan. Migration service yang terintegrasi memastikan transition yang smooth dan safe ke Keycloak, memberikan competitive advantage dalam digital transformation journey.

Artikel ini ditulis tidak mewakili tim developer.

--

--

Fikih Firmansyah
Fikih Firmansyah

Written by Fikih Firmansyah

Back End Developer at Universitas Sumatera Utara || Google Developer Groups Medan

No responses yet