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

CapabilityDescription
SSOOne login for multiple applications
OAuth 2.0 / OIDCToken-based API security
SAML 2.0Enterprise SSO federation
MFAMulti-factor authentication
User ManagementUser stores, roles, claims
ProvisioningAutomated user account creation
Consent ManagementGDPR-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:

  1. Go to Management Console → Service Providers → Add
  2. 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 TypeUse Case
Authorization CodeWeb apps (server-side)
Authorization Code + PKCESPAs and mobile apps
Client CredentialsMachine-to-machine
Refresh TokenToken renewal
Password (legacy)Trusted first-party apps only
Device CodeSmart TVs, CLI tools

Registering an OAuth Application:

  1. Management Console → Service Providers → Add
  2. 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

AuthenticatorTypeDescription
Username/PasswordFirst factorStandard login
TOTPSecond factorGoogle Authenticator, Authy
Email OTPSecond factorOne-time code via email
SMS OTPSecond factorOne-time code via SMS
FIDO2/WebAuthnPasswordlessHardware keys, biometrics
Magic LinkPasswordlessLogin 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)

  1. Register app in Azure AD portal
  2. 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 dialect
  • urn:ietf:params:scim:schemas:core:2.0: SCIM 2.0
  • http://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"

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.