ADR-003: Keycloak for Authentication

Decision Analysis and Resolution: SW360 Authentication Provider

Created by: SW360 Architecture Team
Original Decision: 2022
Reformatted: April 2026
Status: Accepted
Estimated read time: 12 minutes


Table of Contents

  1. Background
  2. Goal
  3. Key Principles
  4. Key Inputs, Assumptions and Restrictions
  5. Options Analysis
  6. Criteria for Making a Decision
  7. Final Decision
  8. Contributors
  9. Implementation Details

Background

SW360 originally used Liferay Portal’s built-in authentication, which coupled user management to the UI layer. With the migration away from Liferay toward a REST-first architecture, several challenges emerged:

  • Liferay Coupling: Authentication was tightly bound to the portal framework
  • No API Authentication: REST API needed OAuth2/OIDC support
  • Enterprise SSO: Customers required integration with corporate identity providers
  • Programmatic Access: CI/CD pipelines needed API tokens
  • Centralized Management: User provisioning across multiple SW360 instances

Why This Decision Matters: Authentication is a critical security component that affects every user interaction, API call, and integration point.


Goal

The goal of this decision analysis is to:

  1. Decouple authentication from the Liferay portal layer
  2. Enable OAuth2/OIDC for modern API authentication
  3. Support enterprise SSO with LDAP/AD/SAML identity providers
  4. Provide centralized user management
  5. Enable API tokens for programmatic access
  6. Maintain self-hosted deployment option (no cloud dependency)

Key Principles

#PrincipleDescription
1Standards-BasedUse OAuth2/OIDC for modern authentication
2Self-Hosted OptionNo mandatory cloud dependencies
3Enterprise IntegrationSupport LDAP, Active Directory, SAML
4Open SourceAvoid vendor lock-in
5CustomizableSupport SW360-specific user storage and events

Key Inputs, Assumptions and Restrictions

TypeDescription
InputSW360 stores users in CouchDB with custom attributes
InputMany deployments use corporate LDAP/Active Directory
InputREST API requires stateless JWT-based authentication
AssumptionEnterprise customers will want SSO integration
AssumptionSelf-hosted deployment is primary model
RestrictionMust support custom user storage provider for CouchDB
RestrictionNo mandatory cloud service dependencies

Options Analysis

Option 1 - Spring Security Standalone

Summary

Use Spring Security’s built-in authentication with a custom UserDetailsService connected to SW360’s CouchDB user database. Build OAuth2 authorization server using Spring Authorization Server.

Conceptual View

graph LR
    A[Client] --> B["Spring Security<br/>+ Spring Auth Server"] --> C["CouchDB (users)"]

Impact / Changes Required

  • Implement custom UserDetailsService for CouchDB
  • Build OAuth2 authorization server endpoints
  • Implement token management (issuance, refresh, revocation)
  • Build admin UI for user management

SWOT Analysis

CategoryAnalysis
Strengths1. No additional component to deploy
2. Full control over authentication flow
3. Tight integration with Spring Boot
4. Single technology stack
Weaknesses1. Must implement OAuth2 server from scratch
2. No built-in admin UI
3. No LDAP/SAML federation out of box
4. Must maintain security updates ourselves
5. Significant development effort
Opportunities1. Customization without limitations
Threats1. Security vulnerabilities from custom implementation
2. High maintenance burden
3. Missing enterprise features

Option 2 - Auth0

Summary

Use Auth0, a cloud-based identity-as-a-service platform providing OAuth2/OIDC, SSO, MFA, and user management out of the box.

Conceptual View

graph LR
    A[Client] --> B["Auth0 (Cloud)"] --> C[SW360 REST]

Impact / Changes Required

  • Configure Auth0 tenant and application
  • Integrate Spring Security with Auth0 JWT validation
  • Sync users between Auth0 and SW360 CouchDB
  • Configure enterprise connections for LDAP/SAML

SWOT Analysis

CategoryAnalysis
Strengths1. Full-featured identity platform
2. Excellent documentation and support
3. Enterprise SSO out of box
4. MFA, passwordless, social login
5. No infrastructure to maintain
Weaknesses1. Cloud dependency—violates self-hosted requirement
2. Subscription costs scale with users
3. Data residency concerns
4. Vendor lock-in
Opportunities1. Rapid implementation
2. Advanced security features
Threats1. Cloud dependency unacceptable for many deployments
2. Pricing changes
3. Service availability dependency

Option 3 - Keycloak

Summary

Use Keycloak, an open-source identity and access management solution from Red Hat. Self-hosted with OAuth2/OIDC, SAML, LDAP federation, and customizable user storage providers.

Conceptual View

graph TB
    A[Client] --> B["Keycloak (Self-host)"] --> C[SW360 REST]
    B --> D["PostgreSQL<br/>(KC users)"]
    B --> E["LDAP<br/>(Federation)"]
    B --> F["CouchDB<br/>(SW360)"]

Impact / Changes Required

  • Deploy Keycloak with PostgreSQL
  • Develop custom user storage provider for CouchDB
  • Create event listener for user synchronization
  • Configure Spring Security for JWT validation

SWOT Analysis

CategoryAnalysis
Strengths1. Fully self-hosted—no cloud dependency
2. Open source with Red Hat backing
3. Enterprise SSO (LDAP, SAML, OIDC) out of box
4. Customizable user storage providers
5. Fine-grained authorization
6. Active community and regular updates
7. MFA, social login, brute force protection
Weaknesses1. Additional component to deploy and maintain
2. Requires PostgreSQL for its data
3. Resource consumption (memory/CPU)
4. Learning curve for administration
5. Custom provider development needed
Opportunities1. Custom SW360 user storage provider
2. Event listeners for user sync
3. Theme customization for branding
Threats1. Keycloak upgrades may break custom providers
2. Must maintain custom provider code
3. OAuth2 flows can be complex to debug

Option 4 - Okta

Summary

Use Okta, an enterprise identity management platform providing comprehensive IAM capabilities with cloud and on-premises options.

Conceptual View

┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│   Client    │────►│    Okta      │────►│  SW360 REST  │
└─────────────┘     │   (Cloud)    │     └──────────────┘
                    └──────────────┘

Impact / Changes Required

  • Purchase Okta subscription
  • Configure Okta tenant
  • Integrate with Spring Security

SWOT Analysis

CategoryAnalysis
Strengths1. Enterprise-grade IAM
2. Excellent support and SLA
3. Comprehensive security features
4. Wide integration ecosystem
Weaknesses1. Commercial product with significant cost
2. Cloud-first (on-prem is limited)
3. Vendor lock-in
4. May be overkill for SW360 needs
Opportunities1. Enterprise customer familiarity
Threats1. Cost prohibitive for open-source project
2. Cloud dependency for most features
3. Acquisition risks

Option 5 - Custom OAuth2 Server

Summary

Build a custom OAuth2 authorization server tailored specifically for SW360’s needs, using libraries like Spring Authorization Server or nimbus-jose-jwt.

Conceptual View

┌─────────────┐     ┌──────────────────────┐     ┌──────────┐
│   Client    │────►│  Custom OAuth2       │────►│ CouchDB  │
└─────────────┘     │  Server              │     │ (users)  │
                    └──────────────────────┘     └──────────┘

Impact / Changes Required

  • Design and implement complete OAuth2 server
  • Build admin UI
  • Implement federation (LDAP, SAML)
  • Ongoing security maintenance

SWOT Analysis

CategoryAnalysis
Strengths1. Complete control over features
2. No external dependencies
3. Tailored to SW360 needs
Weaknesses1. Massive development effort
2. Security risks from custom implementation
3. Must implement all enterprise features
4. Ongoing maintenance burden
5. No community support
Opportunities1. Perfect fit for requirements
Threats1. High risk of security vulnerabilities
2. Resource drain for maintenance
3. Difficult to match enterprise feature set

Criteria for Making a Decision

T-Shirt Sizing Scale

T-Shirt SizeNumeric ValueMeaning
XS1.0Worst for this aspect
S2.5Poor
S-M3.75Below Average
M5.0Average
M-L6.25Above Average
L7.5Good
L-XL8.75Very Good
XL10.0Best for this aspect

Weighted Evaluation Matrix

CriteriaDescriptionWeightSpring StandaloneAuth0KeycloakOktaCustom
RatingScoreRatingScoreRatingScoreRatingScoreRatingScore
Self-Hosted OptionNo cloud dependency10XL100.0XS10.0XL100.0S25.0XL100.0
Enterprise SSOLDAP, AD, SAML support9S22.5XL90.0L-XL78.75XL90.0S22.5
OAuth2/OIDC StandardsModern authentication9M-L56.25XL90.0XL90.0XL90.0M45.0
Open SourceNo vendor lock-in8XL80.0S20.0XL80.0XS8.0XL80.0
Custom User StorageCouchDB integration8L60.0S-M30.0L-XL70.0S-M30.0XL80.0
Development EffortTime to implement8S-M30.0L-XL70.0L60.0L-XL70.0XS8.0
Security UpdatesRegular patches8M40.0XL80.0L-XL70.0XL80.0S20.0
Admin UIUser management UI6XS6.0XL60.0L-XL52.5XL60.0XS6.0
MFA SupportMulti-factor auth6S15.0XL60.0L-XL52.5XL60.0S15.0
Community SupportHelp resources6L45.0L-XL52.5L-XL52.5L45.0XS6.0
CostLicensing/infra cost7XL70.0M35.0L-XL61.25S17.5L52.5
TOTAL524.75597.5767.5575.5435.0

Score Summary

RankOptionTotal ScoreRecommendation
🥇 1Keycloak767.5SELECTED
🥈 2Auth0597.5❌ Cloud dependency
🥉 3Okta575.5❌ Commercial cost
4Spring Standalone524.75❌ Missing enterprise features
5Custom OAuth2435.0❌ Too risky

Final Decision

Selected Option: Keycloak

Rationale

Keycloak was selected as the identity provider for SW360 based on:

  1. Highest Weighted Score (767.5) - Clear winner when balancing all requirements

  2. Self-Hosted (XL) - Critical requirement met:

    • No cloud dependency
    • Full control over user data
    • Compliant with data residency requirements
  3. Enterprise SSO (L-XL) - Built-in support for:

    • LDAP/Active Directory federation
    • SAML 2.0 identity providers
    • OpenID Connect
    • Social login providers
  4. Open Source (XL) - Apache 2.0 license with Red Hat backing:

    • No vendor lock-in
    • Active community
    • Regular security updates
  5. Custom User Storage (L-XL) - Extensible architecture allows:

    • SW360 CouchDB user storage provider
    • Event listeners for user synchronization
    • Custom authentication flows

Implementation Notes

Architecture:

┌─────────┐     ┌──────────┐     ┌──────────────┐
│  User   │────►│ Keycloak │────►│  SW360 REST  │
└─────────┘     └──────────┘     └──────────────┘
                     │                   │
              ┌──────┴──────┐     ┌──────┴──────┐
              │  PostgreSQL │     │   CouchDB   │
              │ (KC users)  │     │(SW360 users)│
              └─────────────┘     └─────────────┘

Custom Providers:

  • sw360-keycloak-user-storage-provider.jar - Reads users from CouchDB
  • sw360-keycloak-event-listener.jar - Syncs Keycloak events to SW360

Review Triggers

This decision should be revisited if:

  • Keycloak project becomes unmaintained
  • Cloud-first deployment becomes primary model
  • Custom provider maintenance becomes unsustainable
  • Alternative open-source IAM with better fit emerges

Contributors

NameRoleContribution
SW360 Architecture TeamDecision MakersRequirements analysis
Security TeamStakeholdersSecurity requirements
Operations TeamStakeholdersDeployment considerations

Implementation Details

Spring Security Configuration

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://keycloak:8083/realms/sw360
          jwk-set-uri: http://keycloak:8083/realms/sw360/protocol/openid-connect/certs

For deployments that must trust more than one issuer/JWKS endpoint (for example, Keycloak plus SW360 authorization-server), configure explicit trusted issuers:

sw360:
  security:
    jwt:
      issuers:
        - issuer-uri: https://sw360.example.com/kc/realms/sw360
          jwk-set-uri: https://keycloak-internal:8083/kc/realms/sw360/protocol/openid-connect/certs
        - issuer-uri: http://localhost:8080/authorization

This configuration pattern is supported by both the SW360 resource-server and the authorization-server resource endpoints (for example /authorization/client-management/** when called with Bearer JWT).

Authentication Flow

  1. User accesses SW360 UI/API
  2. Redirected to Keycloak login
  3. Keycloak authenticates (local DB or federated)
  4. JWT token issued
  5. Token sent to SW360 API
  6. SW360 validates token via JWKS endpoint
  7. User extracted from token claims

API Token Support

For programmatic access, SW360 also supports API tokens:

rest.apitoken.read.validity.days=90
rest.apitoken.write.validity.days=30
rest.apitoken.hash.salt=$2a$04$Software360RestApiSalt

Consequences Summary

Positive

  • ✅ SSO Support—users log in once for multiple applications
  • ✅ JWT Tokens—stateless authentication, scalable
  • ✅ Federation—connect to existing LDAP/AD directories
  • ✅ Security—battle-tested OAuth2/OIDC implementation
  • ✅ API Tokens—native support for service accounts
  • ✅ Self-hosted—no cloud dependency

Negative

  • ⚠️ Additional component to deploy and maintain
  • ⚠️ OAuth2 flows can be complex to troubleshoot
  • ⚠️ Resource usage—Keycloak requires memory/CPU
  • ⚠️ Learning curve for Keycloak administration
  • ⚠️ Custom provider maintenance required

Technical Debt Created

  • Custom user storage provider must be maintained
  • Keycloak version compatibility testing required
  • PostgreSQL database added to infrastructure

Revision History

VersionDateAuthorChanges
1.02022Architecture TeamInitial decision
2.0April 2026Bibhuti Bhusan DashReformatted to DAR/SWOT template
3.0April 2026Gaurav MishraAdded sw360.security.jwt.issuers configuration example