Chapter 5: WSO2 Identity Server
Overview
WSO2 Identity Server (IS) is an open-source identity and access management (IAM) solution. It handles authentication, authorization, single sign-on (SSO), identity federation, and user provisioning across applications and services.
Core Capabilities
| Capability | Description |
|---|---|
| SSO | One login for multiple applications |
| OAuth 2.0 / OIDC | Token-based API security |
| SAML 2.0 | Enterprise SSO federation |
| MFA | Multi-factor authentication |
| User Management | User stores, roles, claims |
| Provisioning | Automated user account creation |
| Consent Management | GDPR-compliant user consent |
Installation and Startup
# Download and extract
wget https://github.com/wso2/product-is/releases/download/v6.1.0/wso2is-6.1.0.zip
unzip wso2is-6.1.0.zip
cd wso2is-6.1.0
# Start the server
./bin/wso2server.sh
# Access management console
# URL: https://localhost:9443/carbon
# Default: admin / admin
Directory Structure:
wso2is-6.1.0/
├── bin/ # Startup scripts
├── conf/ # Configuration files (deployment.toml)
├── repository/
│ ├── components/ # OSGi bundles
│ ├── deployment/ # Deployed artifacts
│ └── resources/ # Security, identity configs
├── dbscripts/ # Database init scripts
└── logs/ # Server logs
Single Sign-On (SSO)
SAML 2.0 SSO
SAML is the standard for enterprise SSO, especially with legacy and on-premises apps.
Flow:
User → App (SP) → Redirect to IS (IdP) → Login → SAML Assertion → App
Registering a Service Provider:
- Go to Management Console → Service Providers → Add
- Configure SAML2 Web SSO:
<!-- SAML SP Configuration -->
<ServiceProvider>
<Issuer>myapp</Issuer>
<AssertionConsumerUrl>https://myapp.com/acs</AssertionConsumerUrl>
<DefaultAssertionConsumerUrl>https://myapp.com/acs</DefaultAssertionConsumerUrl>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<EnableSingleLogout>true</EnableSingleLogout>
<SLOResponseUrl>https://myapp.com/slo</SLOResponseUrl>
<EnableAttributeProfile>true</EnableAttributeProfile>
<IncludeAttributesInResponse>true</IncludeAttributesInResponse>
<EnableResponseSigning>true</EnableResponseSigning>
<EnableAssertionSigning>true</EnableAssertionSigning>
</ServiceProvider>
deployment.toml Configuration:
[saml]
enable = true
[saml.endpoints.idp]
url = "https://localhost:9443/samlsso"
[saml.response]
sign_assertions = true
sign_responses = true
encrypt_assertions = false
OAuth 2.0 and OpenID Connect
OAuth 2.0 secures APIs. OpenID Connect (OIDC) adds an identity layer on top.
Supported Grant Types:
| Grant Type | Use Case |
|---|---|
| Authorization Code | Web apps (server-side) |
| Authorization Code + PKCE | SPAs and mobile apps |
| Client Credentials | Machine-to-machine |
| Refresh Token | Token renewal |
| Password (legacy) | Trusted first-party apps only |
| Device Code | Smart TVs, CLI tools |
Registering an OAuth Application:
- Management Console → Service Providers → Add
- Inbound Authentication → OAuth/OpenID Connect → Configure
# deployment.toml - OAuth2 settings
[oauth]
token_validity = 3600
refresh_token_validity = 86400
enable_pkce = true
[oauth.endpoints]
authorize = "https://localhost:9443/oauth2/authorize"
token = "https://localhost:9443/oauth2/token"
userinfo = "https://localhost:9443/oauth2/userinfo"
jwks = "https://localhost:9443/oauth2/jwks"
Authorization Code Flow (with PKCE):
# Step 1: Redirect user to authorize endpoint
https://localhost:9443/oauth2/authorize?
response_type=code&
client_id=<CLIENT_ID>&
redirect_uri=https://myapp.com/callback&
scope=openid profile email&
code_challenge=<SHA256_HASH>&
code_challenge_method=S256
# Step 2: Exchange code for tokens
curl -X POST https://localhost:9443/oauth2/token \
-d "grant_type=authorization_code" \
-d "code=<AUTH_CODE>" \
-d "redirect_uri=https://myapp.com/callback" \
-d "client_id=<CLIENT_ID>" \
-d "code_verifier=<ORIGINAL_VERIFIER>"
# Response
{
"access_token": "eyJ4NXQiOiJNell4TW1Ga09...",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5...",
"refresh_token": "eyJ4NXQiOiJNell4TW1Ga09...",
"token_type": "Bearer",
"expires_in": 3600
}
Client Credentials Grant (service-to-service):
curl -X POST https://localhost:9443/oauth2/token \
-H "Authorization: Basic <base64(clientId:clientSecret)>" \
-d "grant_type=client_credentials" \
-d "scope=read_data"
Multi-Factor Authentication (MFA)
Available Authenticators
| Authenticator | Type | Description |
|---|---|---|
| Username/Password | First factor | Standard login |
| TOTP | Second factor | Google Authenticator, Authy |
| Email OTP | Second factor | One-time code via email |
| SMS OTP | Second factor | One-time code via SMS |
| FIDO2/WebAuthn | Passwordless | Hardware keys, biometrics |
| Magic Link | Passwordless | Login via email link |
Configuring MFA
Adaptive Authentication Script:
// Step-up authentication based on risk
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function(context) {
var user = context.currentKnownSubject;
var role = hasRole(user, 'admin');
if (role) {
// Require TOTP for admin users
executeStep(2);
}
}
});
};
Conditional MFA Based on IP:
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function(context) {
var ipAddress = context.request.ip;
var trustedIPs = ['10.0.0.0/8', '192.168.1.0/24'];
if (!isTrustedIP(ipAddress, trustedIPs)) {
executeStep(2); // TOTP
}
}
});
};
deployment.toml - Enable TOTP:
[authentication.authenticator.totp]
enable = true
[authentication.authenticator.totp.parameters]
issuer = "MyOrganization"
UseCommonIssuer = true
Identity Federation
Federated Authentication
Connect external identity providers so users can log in with existing accounts.
User → IS → Federated IdP (Google, Azure AD, etc.) → Back to IS → App
Supported Protocols:
- SAML 2.0
- OpenID Connect
- WS-Federation
- Social login (Google, Facebook, GitHub, Microsoft)
Configuring Google as Federated IdP
# deployment.toml
[[authentication.custom_authenticator]]
name = "GoogleOIDCAuthenticator"
enable = true
[authentication.custom_authenticator.parameters]
ClientId = "<GOOGLE_CLIENT_ID>"
ClientSecret = "<GOOGLE_CLIENT_SECRET>"
callbackUrl = "https://localhost:9443/commonauth"
Scope = "openid email profile"
Configuring Azure AD (OIDC)
- Register app in Azure AD portal
- Add Identity Provider in IS:
[[authentication.custom_authenticator]]
name = "AzureADAuthenticator"
enable = true
[authentication.custom_authenticator.parameters]
ClientId = "<AZURE_CLIENT_ID>"
ClientSecret = "<AZURE_CLIENT_SECRET>"
OAuth2AuthzEPUrl = "https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/authorize"
OAuth2TokenEPUrl = "https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token"
callbackUrl = "https://localhost:9443/commonauth"
User Management
User Stores
WSO2 IS supports multiple user store types simultaneously.
Primary User Store (deployment.toml):
[user_store]
type = "database_unique_id"
class = "org.wso2.carbon.user.core.jdbc.UniqueIDJDBCUserStoreManager"
[user_store.properties]
UsernameJavaRegEx = "^[\\S]{3,30}$"
PasswordJavaRegEx = "^[\\S]{5,30}$"
ReadGroups = true
WriteGroups = true
Adding LDAP Secondary User Store:
[[user_store.secondary]]
type = "read_write_ldap_unique_id"
name = "CorporateLDAP"
[user_store.secondary.properties]
ConnectionURL = "ldap://ldap.corp.com:389"
ConnectionName = "cn=admin,dc=corp,dc=com"
ConnectionPassword = "adminpass"
UserSearchBase = "ou=People,dc=corp,dc=com"
GroupSearchBase = "ou=Groups,dc=corp,dc=com"
Roles and Permissions
Super Admin
├── Admin Role
│ ├── /permission/admin/login
│ ├── /permission/admin/manage
│ └── /permission/admin/configure
├── Application Role
│ ├── /permission/applications/view
│ └── /permission/applications/create
└── Custom Roles
└── /permission/custom/*
Creating Roles via SCIM 2.0 API:
curl -X POST https://localhost:9443/scim2/Groups \
-H "Authorization: Basic YWRtaW46YWRtaW4=" \
-H "Content-Type: application/json" \
-d '{
"displayName": "engineering",
"members": [
{"value": "<USER_ID>", "display": "john"}
]
}'
Creating Users via SCIM 2.0 API:
curl -X POST https://localhost:9443/scim2/Users \
-H "Authorization: Basic YWRtaW46YWRtaW4=" \
-H "Content-Type: application/json" \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "john",
"password": "john123",
"emails": [{"value": "john@example.com", "primary": true}],
"name": {"givenName": "John", "familyName": "Doe"}
}'
Claims and Attributes
Claim Management
Claims map user attributes between different systems.
Claim Dialects:
http://wso2.org/claims: WSO2 local dialecturn:ietf:params:scim:schemas:core:2.0: SCIM 2.0http://schemas.xmlsoap.org/ws/2005/05/identity/claims: WS-Federation
Mapping Claims (deployment.toml):
[[claim_mapping]]
local_claim = "http://wso2.org/claims/emailaddress"
oidc_claim = "email"
scim_claim = "emails.work"
saml_claim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
Requesting Claims in OIDC:
# Request specific claims via scope
scope=openid profile email
# Or via claims parameter
claims={
"userinfo": {
"email": {"essential": true},
"phone_number": null
}
}
User Self-Service
Account Recovery
# deployment.toml - Enable self-service
[identity_mgt.password_reset_email]
enable_password_reset = true
[identity_mgt.username_recovery_email]
enable_username_recovery = true
[identity_mgt.account_locking]
enable_account_locking = true
max_failed_attempts = 5
unlock_time_in_minutes = 30
Self-Registration
[identity_mgt.user_self_registration]
enable_self_registration = true
enable_account_lock_on_creation = true
verification_email_validity = 1440
callback_url = "https://myapp.com/verify"
Consent Management
For GDPR and privacy compliance, IS tracks user consent for data sharing.
Consent Flow:
User logs in → IS checks required claims → Consent screen → User approves → Claims shared
Consent API:
# Get user consents
curl -X GET https://localhost:9443/api/identity/consent-mgt/v1.0/consents \
-H "Authorization: Basic YWRtaW46YWRtaW4="
# Revoke consent
curl -X DELETE https://localhost:9443/api/identity/consent-mgt/v1.0/consents/<RECEIPT_ID> \
-H "Authorization: Basic YWRtaW46YWRtaW4="
Integration with WSO2 API Manager
IS as Key Manager for APIM
WSO2 IS can replace the built-in key manager in API Manager for advanced IAM features.
# APIM deployment.toml - Point to IS as key manager
[apim.key_manager]
type = "WSO2-IS"
server_url = "https://is.example.com:9443/services/"
username = "admin"
password = "admin"
[apim.key_manager.configuration]
ServerURL = "https://is.example.com:9443/services/"
TokenURL = "https://is.example.com:9443/oauth2/token"
RevokeURL = "https://is.example.com:9443/oauth2/revoke"
Benefits:
- Centralized token management
- Advanced MFA for API consumers
- Fine-grained authorization
- Federated identity for API access
Common Configurations
Database Setup (Production)
# deployment.toml - MySQL example
[database.identity_db]
type = "mysql"
url = "jdbc:mysql://localhost:3306/identity_db"
username = "wso2carbon"
password = "wso2carbon"
[database.shared_db]
type = "mysql"
url = "jdbc:mysql://localhost:3306/shared_db"
username = "wso2carbon"
password = "wso2carbon"
[database.consent_db]
type = "mysql"
url = "jdbc:mysql://localhost:3306/consent_db"
username = "wso2carbon"
password = "wso2carbon"
Session Management
[session.persistence]
persist_sessions = true
session_cleanup_period = 20160
session_cleanup_timeout = 2
[session]
idle_session_timeout = "15m"
remember_me_session_timeout = "14d"
Key Takeaways
- WSO2 IS handles authentication, authorization, SSO, and user management
- Supports SAML 2.0, OAuth 2.0, and OpenID Connect out of the box
- Adaptive authentication enables risk-based MFA
- Federated authentication connects to external IdPs (Google, Azure AD, etc.)
- SCIM 2.0 APIs enable programmatic user and group management
- IS can serve as the key manager for WSO2 API Manager
- Consent management provides GDPR compliance
Next Steps
Continue to Chapter 6: Development Setup to set up your development environment and tools.