WSO2 Identity Server for Enterprise SSO and Federated Identity: Architecture, Deployment, and Hardening Guide
Prerequisites
- Working knowledge of OAuth2, OpenID Connect, and SAML
- Access to Linux, PostgreSQL, and LDAP or Active Directory
Steps
WSO2 Identity Server is an enterprise IAM platform used to deliver single sign-on, federation, adaptive authentication, and API-driven identity services across hybrid environments. This guide covers its architecture, production deployment patterns, implementation steps, security hardening, and operational troubleshooting.
Overview
WSO2 Identity Server is an open standards-based identity and access management platform built for enterprise single sign-on, identity federation, user lifecycle integration, and fine-grained authentication flows. Organizations use it to centralize authentication for web, mobile, API, and legacy applications while supporting standards such as SAML 2.0, OAuth 2.0, OpenID Connect, SCIM 2.0, and WS-Federation.
Enterprises typically adopt WSO2 Identity Server when they need deployment flexibility, on-premises control, and deep extensibility. Common use cases include workforce SSO, B2B federation with external identity providers, customer identity enablement, and policy-driven adaptive authentication integrated with LDAP or Active Directory.
Architecture
A production WSO2 Identity Server deployment usually includes these core components:
- Authentication and federation engine for local and federated login flows
- User store integration with LDAP, Active Directory, or JDBC user stores
- Identity database for service provider, claim, consent, and token metadata
- Governance and provisioning services for self-service, password policies, and SCIM
- Inbound protocol endpoints for SAML, OAuth2, OIDC, SCIM, and token introspection
Deployment models
- Single node for development or PoC
- Active-active cluster behind a load balancer for HA
- Containerized deployment on Kubernetes for elastic scaling
- Hybrid model with local user stores and cloud applications
Data flow
- A user requests an application protected by OIDC or SAML.
- The application redirects the user to WSO2 Identity Server.
- WSO2 validates credentials against the configured user store or federates to an external IdP.
- Claims are resolved, policies are applied, and a token or assertion is issued.
- The application validates the token and grants access.
For production, externalize the shared database, terminate TLS at the ingress or reverse proxy, and persist configuration through version-controlled files or Kubernetes ConfigMaps and Secrets.
Implementation Guide
1. Install Java and unpack WSO2 Identity Server
sudo apt-get update
sudo apt-get install -y openjdk-17-jdk unzip
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
unzip wso2is-7.0.0.zip -d /opt/
ln -s /opt/wso2is-7.0.0 /opt/wso2is
2. Configure the primary database in repository/conf/deployment.toml
[database.identity_db]
type = "postgres"
url = "jdbc:postgresql://pg01.example.com:5432/wso2_identity"
username = "wso2is"
password = "$env{ID_DB_PASSWORD}"
driver = "org.postgresql.Driver"
[server]
hostname = "login.example.com"
node_ip = "10.10.20.15"
base_path = "https://login.example.com"
[user_store]
type = "read_write_ldap_unique_id"
connection_url = "ldap://ad01.example.com:389"
connection_name = "CN=svc_wso2,OU=Service Accounts,DC=example,DC=com"
connection_password = "$env{LDAP_BIND_PASSWORD}"
base_dn = "DC=example,DC=com"
3. Start the server
export ID_DB_PASSWORD='StrongDbPassword!'
export LDAP_BIND_PASSWORD='StrongLdapPassword!'
/opt/wso2is/bin/wso2server.sh start
tail -f /opt/wso2is/repository/logs/wso2carbon.log
4. Register an OIDC application
- Sign in to the management console at
https://login.example.com:9443/console. - Create an application named
intranet-portal. - Add OpenID Connect inbound auth.
- Set callback URL to
https://portal.example.com/oidc/callback. - Enable authorization code flow and assign claims and roles.
5. Put WSO2 behind NGINX
sudo apt-get install -y nginx
Use a reverse proxy with HSTS, TLS 1.2+, and restricted admin access paths.
Code Examples
apiVersion: v1
kind: ConfigMap
metadata:
name: wso2is-deployment
data:
deployment.toml: |
[server]
hostname = "login.example.com"
base_path = "https://login.example.com"
[transport.https.properties]
proxyPort = 443
import requests
token = requests.post("https://login.example.com/oauth2/token", auth=("client_id","client_secret"), data={"grant_type":"client_credentials","scope":"internal_application_mgt_view"}, timeout=10)
print(token.status_code)
print(token.json())
{
"callbackUrl": "https://portal.example.com/oidc/callback",
"grantTypes": ["authorization_code", "refresh_token"],
"tokenType": "JWT",
"pkceMandatory": true,
"subjectClaimUri": "http://wso2.org/claims/emailaddress"
}
Security Hardening
- Use external PostgreSQL or Oracle with TLS enabled; do not keep embedded databases in production.
- Protect secrets with environment variables or a vault instead of cleartext in
deployment.toml. - Rotate signing and TLS certificates and align token signing algorithms with enterprise crypto policy.
- Restrict admin console exposure by IP allowlisting, VPN, or private ingress.
- Enable secure cookies, HSTS, and proxy-aware headers when deployed behind a load balancer.
- Integrate MFA and adaptive authentication for privileged users and high-risk logins.
- Forward audit logs to SIEM and monitor failed logins, token issuance spikes, and admin changes.
Comparison
| Feature | WSO2 Identity Server | Okta | Keycloak |
|---|---|---|---|
| Pricing | Subscription/support oriented, self-hosted economics | SaaS subscription per user/app | Open source, enterprise support via Red Hat build options |
| Deployment | On-prem, VM, container, Kubernetes, hybrid | Primarily SaaS | On-prem, container, Kubernetes |
| Scalability | Strong with clustered and K8s deployments | High SaaS scalability | Good, depends on architecture and tuning |
| Security | Strong standards support, adaptive auth, enterprise federation | Mature SaaS controls and integrations | Strong standards support, flexible but more ops-driven |
Troubleshooting
1. Database connectivity failure
Log sample:
ERROR {org.wso2.carbon.ndatasource.core.DataSourceManager} - Error in looking up data source: jdbc/WSO2CarbonDB javax.naming.NamingException: Cannot create resource factory instance [Root exception is java.sql.SQLException: Connection refused]
Fix: Verify PostgreSQL reachability, JDBC URL, firewall rules, and that the driver JAR is present if required by the version.
2. LDAP bind failure
Log sample:
WARN {org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager} - LDAP authentication failed for user: alice@example.com cause: javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
Fix: Revalidate bind DN format, password rotation status, and whether the account is locked or restricted to specific hosts.
3. OIDC redirect mismatch
Log sample:
ERROR {org.wso2.carbon.identity.oauth.endpoint.authz.OAuth2AuthzEndpoint} - Callback URL mismatch. Provided: https://portal.example.com/callback, Registered: https://portal.example.com/oidc/callback
Fix: Ensure the exact redirect URI matches the registered application value, including path, scheme, and trailing slash behavior.
Best Practices
Do
- Separate runtime, config, and secret management using Git for config and a vault for secrets.
- Use HA with at least two nodes behind a health-checked load balancer.
- Map enterprise roles to application claims instead of hardcoding authorization in apps.
- Enable PKCE for OIDC clients even for confidential clients where policy requires it.
Don't
- Do not expose port 9443 directly to the internet without access restrictions.
- Do not use the embedded H2 database in production.
- Do not store LDAP or DB passwords in plaintext files.
- Do not skip log centralization; identity incidents are difficult to investigate without correlated audit trails.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI