Thursday, December 22, 2016

Self User Registration feature WSO2 Identity Server 5.3.0.

In this blog post, I am explaining about the self-registration feature in WSO2 Identity Server 5.3.0 release which will be released soon.


Self User Registration 


In previous releases of Identity Server (IS 5.0.0, 5.1.0, 5.2.0), it can be used UserInformationRecovery Soap Service for self-registration feature.

You can follow this for more information about the soap service and how it can be configured.

Rest API support for Self-registration is available in IS 5.3.0 release.

UserInformationRecovery Soap APIs is also available in IS 5.3.0 release for supporting backward compatibility. You can try the Rest service through Identity Server login page (https://localhost:9443/dashboard)


You can't test the SOAP service through the login page. It can be tested using the user info recovery sample


How to configure self-registration rest API


  1. Verify following configurations in <IS_HOME>/repository/conf/identity/identity.xml file
    • <EventListener ype="org.wso2.carbon.user.core.listener.UserOperationEventListener"name="org.wso2.carbon.identity.mgt.IdentityMgtEventListener" orderId="50" enable="false"/>
    • <EventListener type="org.wso2.carbon.user.core.listener.UserOperationEventListener" name="org.wso2.carbon.identity.governance.listener.IdentityStoreEventListener" orderId="97" enable="true">
    • <EventListener type="org.wso2.carbon.user.core.listener.UserOperationEventListener" name="org.wso2.carbon.identity.scim.common.listener.SCIMUserOperationListener  orderId="90" enable="true"/>
  2. Configure email setting in <IS_HOME>/repository/conf/output-event-adapters.xml file. 
  3. Start the WSO2 IS server and login to the management console.
  4. Click on Resident found under the Identity Providers section on the Main tab of the management console.
  5. Expand the Account Management Policies tab, then the Password Recovery tab and configure the following properties as required.
  6. Enable account lock feature to support self-registration with email confirmation feature




Once the user is registered, a notification will be sent to the user's email account if the
"Enable Notification Internally Management" property is true.

Note: If it is not required to lock user once the registration is done, it is required disable both 
Enable Account Lock On Creation and Enable Notification Internally Management properties. Otherwise it will send a confirmaiton mail to the users email account.


APIs

  • Register User
This API is used to create the user in Identity Server. You can try this from login page. (https://localhost:9443/dashboard/)

Click Register Now button and submit the form with data. Then it will send a notification and lock the user based on the configuration. 
  • Resend Code
This is used to resend the confirmation mail again.

You can try this from login page. First, register a new user and try to login to the Identity Server using the registered user credentials without click on the email link received via Identity Server for confirming the user. Then, you will see following in the login page. Click Re-Send button to resend the confirmation link.



  • Validate Code
This API will be used to validate account confirmation link sent in the email. 

Monday, October 3, 2016

Password History Extension for WSO2 Identity Server 5.2.0




WSO2 Identity Server 5.2.0 was released in last month (September 2016). You can download the Identity Sever 5.2.0 from here.

It supports a lot of Identity and Access Management features OOTB and you can find them from here.
Currently, In Identity Server 5.2.0 version does not support password history validation feature OOTB.  (This feature will be supported OOTB in next release which is planned in December 2016).
Although this feature is not supported OOTB, it can be supported easily through an extension. In this blog, I have implemented a sample  which will support following features for IS 5.2.0.


  • Password cannot have been used in previous 'n' password changes
  • Password cannot have been previously used in past 'm' hours. 

Here the 'n' and 'm' should be configurable parameters. 


You can go through following steps to add password history feature in IS 5.2.0.
  1. Download Identity Server 5.2.0 from here
  2. Go through the installation guide and install Java and Maven.
  3. Download the Extention source code from here.
  4. Goto inside password_history folder and run the command "mvn clean install"
  5. Copy password_history/target/org.wso2.custom-1.0.0.jar file to <IS_HOME>/repository/components/dropins folder
  6. password_history/src/main/resources/dbScripts directory contains following db scripts files. Run the relevant configuration file based on your database configured in identity.xml file.
    • db2.sql  
    • informix.sql 
    • mysql.sql    
    • oracle.sql
    • h2.sql   
    • mssql.sql     
    • oracle_rac.sql  
    • postgresql.sql
  7. Copy password_history/src/main/resources/password-history-identity-mgt.properties file into <IS_HOME>/repository/conf/Identity directory. It has following configrable parameters and configure them according to the requirements.
    • #If true, password history feature will be enabled
    • PasswordHistory.Enable=true

    • #Password cannot have been used in the previous 'X' password changes
    • PasswordHistory.Count=5

    • #Password cannot have been previously used in the past 24 hours
    • PasswordHistory.Time=24

    • #Password Digest Algorithm
    • PasswordHistory.hashingAlgorithm=SHA-256

    • #Password History data store extension point
    • PasswordHistory.dataStore=org.wso2.custom.store.impl.DefaultPasswordHistoryDataStore
  8. Start Identity Server
  9. Then you are done. You can try the feature by adding user and updating credentials.

Tuesday, March 8, 2016

How to Write a Custom User Store Manager - WSO2 Identity Server 5.1.0

WSO2 Identity Sever OOTB support following user stores.
  • org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager
  • org.wso2.carbon.user.core.ldap.ReadOnlyLDAPUserStoreManager
  • org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager
  • org.wso2.carbon.user.core.ldap.ActiveDirectoryLDAPUserStoreManager
  • org.wso2.carbon.identity.user.store.remote.CarbonRemoteUserStoreManger
There are some cases, we have to write a custom implementation. Here I am explaining an step by step guide of how to write a custom users store manager for Identity Server 5.1.0. 

Requirement: A company already has a user database and need to authenticate to Identity Server through that database.

Following is the schema of USER database.


CREATE TABLE TEST_USER (
 USER_ID INT NOT NULL PRIMARY KEY,
    USER_NAME VARCHAR(100),
    ENCRYPTED_USER_PASSWORD VARCHAR(100),
    EMAIL_ADDRESS VARCHAR(240),
    EMPLOYEE_ID INT
);

INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (1, "testadmin", "testpass", "admin@act.org", 1000);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (2, "user1", "user1", "user1@act.org", 1001);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (3, "user2", "user2", "user2@act.org", 1002);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (4, "user3", "user3", "user3@act.org", 1003);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (5, "user4", "user4", "user4@act.org", 1004);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (6, "user5", "user5", "user5@act.org", 1005);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (7, "user6", "user6", "user6@act.org", 1006);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (8, "user7", "user7", "user7@act.org", 1007);
INSERT INTO TEST_USER (USER_ID, USER_NAME, ENCRYPTED_USER_PASSWORD, EMAIL_ADDRESS, EMPLOYEE_ID) VALUES (9, "user8", "user8", "user8@act.org", 1008);


Writing Custom User Store Manager
  • You can find the sample code from here
  • Our custom User store is a jdbc based user store and we can write it by extending the org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager.
  • We need to override the doAuthenticate method to authenticate using the new database. 


 @Override
    public boolean doAuthenticate(String userName, Object credential) throws UserStoreException {

        if (CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME.equals(userName)) {
            log.error("Anonymous user trying to login");
            return false;
        }

        Connection dbConnection = null;
        ResultSet rs = null;
        PreparedStatement prepStmt = null;
        String sqlstmt = null;
        String password = (String) credential;
        boolean isAuthed = false;

        try {
            dbConnection = getDBConnection();
            dbConnection.setAutoCommit(false);
            sqlstmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.SELECT_USER);

            prepStmt = dbConnection.prepareStatement(sqlstmt);
            prepStmt.setString(1, userName);

            rs = prepStmt.executeQuery();

            if (rs.next()) {
                String storedPassword = rs.getString("ENCRYPTED_USER_PASSWORD");
                if ((storedPassword != null) && (storedPassword.trim().equals(password))) {
                    isAuthed = true;
                }
            }
        } catch (SQLException e) {
            throw new UserStoreException("Authentication Failure. Using sql :" + sqlstmt);
        } finally {
            DatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt);
        }

        if (log.isDebugEnabled()) {
            log.debug("User " + userName + " login attempt. Login success :: " + isAuthed);
        }

        return isAuthed;
    }
  • We have to define custom SQL queries and we can make them as configurable by overriding getDefaultUserStoreProperties method as follows.

  @Override
    public org.wso2.carbon.user.api.Properties getDefaultUserStoreProperties() {
        Properties properties = new Properties();
        properties.setMandatoryProperties(CustomUserStoreManagerConstants.MANDATORY_PROPERTIES.toArray
                (new Property[CustomUserStoreManagerConstants.MANDATORY_PROPERTIES.size()]));
        properties.setOptionalProperties(CustomUserStoreManagerConstants.OPTIONAL_PROPERTIES.toArray
                (new Property[CustomUserStoreManagerConstants.OPTIONAL_PROPERTIES.size()]));
        properties.setAdvancedProperties(CustomUserStoreManagerConstants.ADVANCED_PROPERTIES.toArray
                (new Property[CustomUserStoreManagerConstants.ADVANCED_PROPERTIES.size()]));
        return properties;
    }


  • We can set the mandatory, optional and advanced configuration as follows. 

package com.wso2.carbon.custom.user.store.manager;

import org.wso2.carbon.user.api.Property;
import org.wso2.carbon.user.core.UserStoreConfigConstants;
import org.wso2.carbon.user.core.jdbc.JDBCRealmConstants;

import java.util.ArrayList;

public class CustomUserStoreManagerConstants {

    public static final ArrayList<Property> MANDATORY_PROPERTIES = new ArrayList<Property>();
    public static final ArrayList<Property> OPTIONAL_PROPERTIES = new ArrayList<Property>();
    public static final ArrayList<Property> ADVANCED_PROPERTIES = new ArrayList<Property>();

    static {
        setMandatoryProperty(JDBCRealmConstants.DRIVER_NAME, "Driver Name", "", "Full qualified driver name");
        setMandatoryProperty(JDBCRealmConstants.URL, "Connection URL", "", "URL of the user store database");
        setMandatoryProperty(JDBCRealmConstants.USER_NAME, "User Name", "", "Username for the database");
        setMandatoryProperty(JDBCRealmConstants.PASSWORD, "Password", "", "Password for the database");

        setProperty(UserStoreConfigConstants.disabled, "Disabled", "false", UserStoreConfigConstants.disabledDescription);
        setProperty("ReadOnly", "Read Only", "true", "Indicates whether the user store of this realm operates in the user read only mode or not");
        setProperty(UserStoreConfigConstants.SCIMEnabled, "SCIM Enabled", "false", UserStoreConfigConstants.SCIMEnabledDescription);

        setAdvancedProperty("SelectUserSQL", "Select User SQL", "SELECT * FROM TEST_USER WHERE USER_NAME=?", "");
        setAdvancedProperty("UserFilterSQL", "User Filter SQL", "SELECT USER_NAME FROM TEST_USER WHERE USER_NAME LIKE" +
                " ? ORDER BY USER_NAME", "");
        setAdvancedProperty("IsUserExistingSQL", "Is User Existing SQL", "SELECT USER_NAME FROM TEST_USER WHERE " +
                "USER_NAME=? ", "");
    }

    private static void setProperty(String name, String displayName, String value, String description) {
        Property property = new Property(name, value, displayName + "#" + description, null);
        OPTIONAL_PROPERTIES.add(property);
    }

    private static void setMandatoryProperty(String name, String displayName, String value, String description) {
        Property property = new Property(name, value, displayName + "#" + description, null);
        MANDATORY_PROPERTIES.add(property);
    }

    private static void setAdvancedProperty(String name, String displayName, String value, String description) {
        Property property = new Property(name, value, displayName + "#" + description, null);
        ADVANCED_PROPERTIES.add(property);
    }
}



  • Register Custom User Store Manager in OSGI framework

/**
 * @scr.component name="com.wso2.carbon.custom.user.store.manager.component" immediate="true"
 * @scr.reference name="realm.service"
 * interface="org.wso2.carbon.user.core.service.RealmService"cardinality="1..1"
 * policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
 */
public class CustomUserStoreManagerServiceComponent {

    private static Log log = LogFactory.getLog(CustomUserStoreManagerServiceComponent.class);
    
    private static RealmService realmService;
    
    protected void activate(ComponentContext ctxt) {
     Hashtable<String, String> props = new Hashtable<String, String>();       
        CustomUserStoreManager customUserStoreManager = new CustomUserStoreManager();
        ctxt.getBundleContext().registerService(UserStoreManager.class.getName(), customUserStoreManager, props);
        log.info("CustomUserStoreManager bundle activated successfully..");
    }

    protected void deactivate(ComponentContext ctxt) {
        if (log.isDebugEnabled()) {
            log.info("CustomUserStoreManager bundle is deactivated");
        }
    }
    
    protected void setRealmService(RealmService realmService) {
        log.debug("Setting the Realm Service");
        CustomUserStoreManagerServiceComponent.realmService = realmService;
    }

    protected void unsetRealmService(RealmService realmService) {
        log.debug("UnSetting the Realm Service");
        CustomUserStoreManagerServiceComponent.realmService = null;
    }

    public static RealmService getRealmService() {
        return realmService;
    }
}


Identity Server Configurations. 


  • Compile the custom user store manager code and then you will get com.wso2.carbon.custom.user.store.manager-1.0.0.jar OSGI bundlle.
  • Copy com.wso2.carbon.custom.user.store.manager-1.0.0.jar into <IS_HOME>/repository/components/dropins folder.
  • Configure new database in <IS_HOME>//repository/conf/datasources/master-datasources.xml file as follows

<datasource>
    <name>CustomUserDB</name>
    <description>Custom User Database</description>
    <jndiConfig>
        <name>jdbc/CustomUserDB</name>
    </jndiConfig>
    <definition type="RDBMS">
        <configuration>
            <url>jdbc:mysql://localhost:3306/Custom</url>
            <username>root</username>
            <password>root</password>
            <driverClassName>com.mysql.jdbc.Driver</driverClassName>
            <maxActive>50</maxActive>
            <maxWait>60000</maxWait>
            <testOnBorrow>true</testOnBorrow>
            <validationQuery>SELECT 1</validationQuery>
            <validationInterval>30000</validationInterval>
        </configuration>
    </definition>
</datasource>



  • Start Identity Server.
  • Go to Add User button inside Home/Identity.




  • Then you can fill the configurations as above image
  • Then assign login permission to Internal/everyone role 
  • Try to login to management console using user1/user1



Thursday, February 18, 2016

WSO2 Identity Server 5.1.0 behind Proxy(Load Balancer)

WSO2 Identity Server behind Proxy or Load Balancer.

In this blog, I am going to explain step by step guide to how to configure WSO2 Identity Server 5.1.0 with a proxy port and proxy host.

Configuring Proxy Port


By default WSO2 Identity Server is running on 9443 port. Here I am going to explain the way of configuring a proxy port of 443.

  • Open <wso2is-5.1.0>/repository/conf/tomcat/catalina-server.xml file and add the proxy port 443 in https connector as follows.
        
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"

           port="9443"

           proxyPort="443"

Note: It is not possible to configure proxy port from load balancer itself since there is a post request while authenticating to IS Dashboard. So, If you are planning to use Identity server Dashboard, this configuration is a must.




Configuring Proxy Host


1. Use the same hostname in both Identity Server and Loadbalancer
  • Open <wso2is-5.1.0>/repository/conf/carbon.xml file and configure the hostname and management hostname as follows


    <HostName>wso2.is.com</HostName>

    <MgtHostName>wso2.is.com</MgtHostName>


  • Create a new Keystore with the new hostname. Following is the keytool command to create new

keytool -genkey -alias wso2carbon -keyalg RSA -keysize 1024 -dname "CN=wso2.is.com,OU=Home,O=Home,L=SL,S=WS,C=LK" -keypass wso2carbon -keystore wso2carbon.jks -storepass wso2carbon


Create new two keystores for client-trustore.jks and wso2carbon.jks. 

You can follow [1] for more information on how to configure keystores in WSO2 servers. 

  • Configure Nginx configuration as follows


upstream ssl.wso2.as.com {
    server wso2.is.com:9443;
}

server {
listen 443;
    server_name wso2.is.com;
    client_max_body_size 100M;

    ssl on;
    ssl_certificate /etc/ssl/nginx/nginx-repo.crt;
    ssl_certificate_key /etc/ssl/nginx/nginx-repo.key;

    location / {
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


                proxy_redirect https://ssl.wso2.as.com https://wso2.is.com;

                proxy_pass https://ssl.wso2.as.com;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
    }

}


You need to change the path of certificate and certificate_key. 


  • Configure proxy port and host in <wso2is-5.1.0> /repository/deployment/server/jaggeryapps/dashboard/conf/site.json file as follows


{
    "proxy" : {
        "proxyHost" : "wso2.is.com",
        "proxyHTTPSPort" : "443",
        "proxyContextPath" : "",
        "servicePath" : "/services"
    }
}

  • Configure proxy port and host in <wso2is-5.1.0> /repository/deployment/server/jaggeryapps/portal/conf/site.json file as follows
{

{
    "proxy" : {
        "proxyHost" : "wso2.is.com",
        "proxyHTTPSPort" : "443",
        "proxyContextPath" : ""
    },
    "fido" : {
        "appId" : ""
    }
}

  • Configure proxy port and host in <wso2is-5.1.0> /repository/deployment/server/webapps/shindig/WEB-INF/web.xml

<context-param>
        <param-name>system.properties</param-name>
        <param-value>
            <![CDATA[
        shindig.host=wso2.is.com
        shindig.port=443
        aKey=/shindig/gadgets/proxy?container=default&url=
     ]]>

  • Import the load balancer certificate into client-trustore.jks file.


Note: Load balancer certificate should be IS hostname. 



2. Configure a proxyName in catalina-server.xml file. 




If you want to use a proxyname which is diffrent from the Identity Server hostname, you can do it configuring catalina-server.xml file.

If your load balancer hostname is is.wso2.com and Identity Server hostname a-s00001572, following configurations need to be done inorder to work Identity Server behind that proxy name and port.


  • Open <wso2is-5.1.0>/repository/conf/carbon.xml file and configure the hostname and management hostname as follows


    <HostName>a-s00001572</HostName>

    <MgtHostName>a-s00001572</MgtHostName>



    • Create a new Keystore with the new hostname. Following is the keytool command to create new

    keytool -genkey -alias wso2carbon -keyalg RSA -keysize 1024 -dname "a-s00001572,OU=Home,O=Home,L=SL,S=WS,C=LK" -keypass wso2carbon -keystore wso2carbon.jks -storepass wso2carbon
    


    Create new two keystores for client-trustore.jks and wso2carbon.jks. 

    You can follow [1] for more information on how to configure keystores in WSO2 servers. 


    • Configure Nginx configuration as follows

    upstream ssl.wso2.as.com {
        server A-S00001572:9443;
    }
    
    server {
    listen 443;
        server_name is.wso2.com;
    
        client_max_body_size 100M;
    
        ssl on;
        ssl_certificate /etc/ssl/nginx/nginx-repo.crt;
        ssl_certificate_key /etc/ssl/nginx/nginx-repo.key;
    
        location / {
                    proxy_set_header X-Forwarded-Host $host;
                    proxy_set_header X-Forwarded-Server $host;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
                    proxy_redirect https://A-S00001572:9443 https://A-S00001572;
    
    
                    proxy_pass https://ssl.wso2.as.com;
                    proxy_http_version 1.1;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection "upgrade";
        }
    
    }


    You need to change the path of certificate and certificate_key.

    • Configure proxy port and host in <wso2is-5.1.0> /repository/deployment/server/jaggeryapps/dashboard/conf/site.json file as follows


    {
        "proxy" : {
            "proxyHost" : "wso2.is.com",
            "proxyHTTPSPort" : "443",
            "proxyContextPath" : "",
            "servicePath" : "/services"
        }
    }
    

    • Configure proxy port and host in <wso2is-5.1.0> /repository/deployment/server/jaggeryapps/portal/conf/site.json file as follows
    {

    {
        "proxy" : {
            "proxyHost" : "wso2.is.com",
            "proxyHTTPSPort" : "443",
            "proxyContextPath" : ""
        },
        "fido" : {
            "appId" : ""
        }
    }
    

    • Configure proxy port and host in <wso2is-5.1.0> /repository/deployment/server/webapps/shindig/WEB-INF/web.xml

    <context-param>
            <param-name>system.properties</param-name>
            <param-value>
                <![CDATA[
            shindig.host=wso2.is.com
            shindig.port=443
            aKey=/shindig/gadgets/proxy?container=default&url=
         ]]>
    

    • Import the load balancer certificate into client-trustore.jks file.


    Note : Load balancer certificate should be IS hostname. 


    Running the Server. 



    Now you are done. You will be able to log into Identity Server Management Console and Dashboard web app from following URLs. 


    Management Console : https://wso2.is.com/carbon/
    Dashboard :https://wso2.is.com/dashboard



    [1] https://docs.wso2.com/display/Carbon440/Configuring+Keystores+in+WSO2+Products

    Friday, February 27, 2015

    Enabling SSO for WSO2 Servers

    You can follow [1] for enabling SSO for WSO2 Servers.


    When you configure SSO for WSO2 Servers, either you have to share the user stores or internal roles, otherwise you will end up with a authorization failure



    In this blog post I am going to post the steps to share the internal roles in WSO2IS and WSO2ESB.


    i)  Download WSO2IS 5.0.0 and WSO2ESB 4.8.1
    ii) Configure WSO2ESB's offset to 1 from <ESB_HOME>/repository/conf/carbon.xml file

    iii) Open <IS_HOME>/repository/conf/datasource/master-datasources.xml file and add following data-source configuration

         <datasource>
                <name>WSO2UM_DB</name>
                <description>The datasource used for user management</description>
                <jndiConfig>
                    <name>jdbc/WSO2UM_DB</name>
                </jndiConfig>
                <definition type="RDBMS">
                    <configuration>
               <url>jdbc:mysql://localhost:3306/userstore?autoReconnect=true&amp;relaxAutoCommit=true&amp;
                        </url>
                        <username>db_username</username>
                        <password>db_password</password>
                        <driverClassName>com.mysql.jdbc.Driver</driverClassName>
                        <maxActive>50</maxActive>
                        <maxWait>60000</maxWait>
                        <testOnBorrow>true</testOnBorrow>
                        <validationQuery>SELECT 1</validationQuery>
                        <validationInterval>30000</validationInterval>
                    </configuration>
                </definition>
            </datasource>

    iv) Open <ESB_HOME>/repository/conf/datasource/master-datasources.xml file and add following data-source configuration

         <datasource>
                <name>WSO2UM_DB</name>
                <description>The datasource used for user management</description>
                <jndiConfig>
                    <name>jdbc/WSO2UM_DB</name>
                </jndiConfig>
                <definition type="RDBMS">
                    <configuration>
               <url>jdbc:mysql://localhost:3306/userstore?autoReconnect=true&amp;relaxAutoCommit=true&amp;
                        </url>
                        <username>db_username</username>
                        <password>db_password</password>
                        <driverClassName>com.mysql.jdbc.Driver</driverClassName>
                        <maxActive>50</maxActive>
                        <maxWait>60000</maxWait>
                        <testOnBorrow>true</testOnBorrow>
                        <validationQuery>SELECT 1</validationQuery>
                        <validationInterval>30000</validationInterval>
                    </configuration>
                </definition>
            </datasource>


    v) Open <IS_HOME>/repository/conf/user-mgt.xml file and configure datasource as follows [change the property dataSource ]


    <Configuration>
            <AddAdmin>true</AddAdmin>
                    <AdminRole>admin</AdminRole>
                    <AdminUser>
                         <UserName>admin</UserName>
                         <Password>admin</Password>
                    </AdminUser>
                <EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in this role sees the registry root -->
                <Property name="dataSource">jdbc/WSO2UM_DB</Property>
            </Configuration>

     vi)

    v) Open <ESB_HOME>/repository/conf/user-mgt.xml file and configure datasource as follows [change the property dataSource ]


    <Configuration>
            <AddAdmin>true</AddAdmin>
                    <AdminRole>admin</AdminRole>
                    <AdminUser>
                         <UserName>admin</UserName>
                         <Password>admin</Password>
                    </AdminUser>
                <EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in this role sees the registry root -->
                <Property name="dataSource">jdbc/WSO2UM_DB</Property>
            </Configuration>
     v) Open <IS_HOME>/repository/conf/user-mgt.xml file and configure datasource as follows [change the property dataSource ]


    <Configuration>
            <AddAdmin>true</AddAdmin>
                    <AdminRole>admin</AdminRole>
                    <AdminUser>
                         <UserName>admin</UserName>
                         <Password>admin</Password>
                    </AdminUser>
                <EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in this role sees the registry root -->
                <Property name="dataSource">jdbc/WSO2UM_DB</Property>
            </Configuration>

    vii) Add mysql connector jar [2] to <IS_HOME>/repository/components/lib folder


    viii) Add mysql connector jar [2] to <ESB_HOME>/repository/components/lib folder

    viii) Create Database named  WSO2UM_DB and run following script on it

    <IS_HOME>/dbscripts/mysql.sql


    viii) Now start both WSO2IS and WSO2ESB. When you add internal role in WSO2IS, it will show in the WSO2ESB as well.


    ix) Now you can create a user in WSO2IS and assign a internal role which has login permission to that user. Then try to log into ESB, you will be able to successfully log in.








    [1] https://docs.wso2.com/display/IS500/Enabling+SSO+for+WSO2+Servers
    [2] http://dev.mysql.com/downloads/connector/j/

    Saturday, September 13, 2014

    How to Lock, user account in WSO2 Identity Server 5.0.0

    WSO2 Identity Server can be configured to lock the user account for exceeding maximum login attempts. It can be done from Identity Management feature and you can use [1] for configuring the identity management feature.

    There can be scenarios where admin wants to lock and unlock  user account and Identity Server supports this feature through Management Console. Following steps can be used to lock user account through admin console.

    Step1

    Download and Install WSO2 Identity Server 5.0.0 from here.

     Step2

    Open web browser and go to   https://localhost:9443/carbon/admin


    1


    Login with following credentials

    Username :  admin
    Password  : admin


    Step3


    Assign login permission to internal/everyone role.

    Step4


    Follow steps in here to add a new user and assign internal/everyone role to created user.

    Step5


    Sign out from the admin user and try to log to the Identity Server with newly added user's credentials
    You should be able to log in since account is not lock by default.

    Step6


    Login as admin and go to configure tab and select claim Management. Then select 'http://wso2.org/claims' link and click edit the Account Lock claim. Click the Supported by Default chekbox and save the changes.

    Step7


    Then go to User Account Edit page and type true in Account Locked Field. Then the user is locked.







    [1] https://docs.wso2.com/pages/viewpage.action?pageId=34612027

    Tuesday, June 17, 2014

    Secure passwords in Password Callback Handler using WSO2 Carbon Secure Vault


    In WSO2 carbon products, password Callback handler class can be used to provide passwords needed for Rampart engine to build username tokens and create signatures when sending messages. Apache Rampart is the Axis2 module which providers WS-Security feature to Axis2 Web Services. You can find a detailed explanation of password callback from here.

    Following is a sample callback handler class

    public class PWCBHandler implements CallbackHandler {
    
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    
            for (Callback callback : callbacks) {
                WSPasswordCallback pwcb = (WSPasswordCallback) callback;
                String id = pwcb.getIdentifer();
                int usage = pwcb.getUsage();
                if (usage == WSPasswordCallback.USERNAME_TOKEN) {
                    // Logic to get the password to build the username token
                    if ("admin".equals(id)) {
                        pwcb.setPassword("admin");
                    }
                } else if (usage == WSPasswordCallback.SIGNATURE || usage == WSPasswordCallback.DECRYPT) {
                    // Logic to get the private key password for signature or decryption
                    if ("client".equals(id)) {
                        pwcb.setPassword("apache");
                    }
                    if ("service".equals(id)) {
                        pwcb.setPassword("apache");
                    }
                }
            }
        }
    }
    





    WSO2 Carbon is shipped with a Secure Vault implementation which is a modified version of synapse Secure Vault. It can be used to avoid the hard coding of password in above example and retrieve it from file in secured manner.

    Following example will show you how to configure WSO2 Secure Vault for Password Callback Handler with WSO2 Identity Server 5.0.0


    Step1 : Download the WSO2 Identity Server 5.0.0 from here 
    Step2 : Create a config file named test_conf1.xml in <carbon_home>/repository/conf directory and add following text


    <testconf>
       <module serverURL="local://services/" remote="false">
           <password>admin</password>
       </module> 
    </testconf>

    Step3Add following line to <carbon_home>/repository/conf/security/cipher-tool.properties file


    testconf.module.password=test_conf1.xml//testconf/module/password,true

    Step4 : Add following line to <carbon_home>/repository/conf/security/cipher-text.properties file


    testconf.module.password=[admin]

    Step5 : Go to <carbon_home>/bin directory and execute "sh ciphertool.sh -Dconfigure" command. Then it will ask you to enter the primary key store password. Type "wso2carbon" as the password

    Step6 : Then test_conf1.xml file will be updated as follows


    <<?xml version="1.0" encoding="UTF-8" standalone="no"?><testconf xmlns:svns="http://org.wso2.securevault/configuration">
       <module remote="false" serverURL="local://services/">
           <password svns:secretAlias="testconf.module.password">password</password>
       </module>
     </testconf>

    you can see the cipher-text.properties file and the password should encrypted as follows


    testconf.module.password=PFQC+qjKxmDePuiR5kSSTOx6suR48UKbDpcEEZ57TcXsHIlnP+I6E2ZXOBtZ91Fk+z3b8vWV84GB\nzn9q+ZQZ0XmdTUzNTMFMV/rpkT3OVhN9MUCjlHIORhcNMt9oWiVKaQ5tO2AmFg5IIqvG/FO51q3o\nx+L8a2sF3JH9G1m203s\=
    Step7 : Following class can be used to resolve the password
    /*
     * Copyright (c) 2006, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.sample.securevault;
    
    
    import org.apache.axiom.om.OMElement;
    import org.apache.axiom.om.impl.builder.StAXOMBuilder;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.wso2.carbon.utils.CarbonUtils;
    import org.wso2.securevault.SecretResolver;
    import org.wso2.securevault.SecretResolverFactory;
    import javax.xml.namespace.QName;
    import javax.xml.stream.XMLStreamException;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class TestConf {
        private static final Log log = LogFactory.getLog(TestConf.class);
        private String password;
        private String serverURL;
        private String remote;
        public TestConf() {
            InputStream fileInputStream = null;
            String configPath = CarbonUtils.getCarbonHome()+ File.separator + "repository" + File.separator + "conf" +
           File.separator + "conf-test1.xml";
           File registryXML = new File(configPath);
            if (registryXML.exists()) {
                try {
                    fileInputStream = new FileInputStream(registryXML);
                    StAXOMBuilder builder = new StAXOMBuilder(fileInputStream);
                    builder.setNamespaceURIInterning(true);
                    OMElement configElement = builder.getDocumentElement();
                    //Initialize the SecretResolver providing the configuration element.
                   SecretResolver secretResolver = SecretResolverFactory.create(configElement, false);
                    OMElement module = configElement.getFirstChildWithName(new QName("module"));
                    if (module != null) {
                       //same entry used in cipher-text.properties and cipher-tool.properties.
                        String secretAlias = "testconf.module.password";
                      //Resolved the secret password.
                        if (secretResolver != null && secretResolver.isInitialized()) {
                            if (secretResolver.isTokenProtected(secretAlias)) {
                                password = secretResolver.resolve(secretAlias);
                           } else {
                               password = module.getFirstChildWithName(new QName("password")).getText();
                            }
                       }
                        serverURL = module.getAttributeValue(new QName("serverURL"));
                        remote = module.getAttributeValue(new QName("remote"));
                   }
                } catch (XMLStreamException e) {
                    log.error("Unable to parse conf-test1.xml", e);
                } catch (IOException e) {
                   log.error("Unable to read conf-test1.xml", e);
                } finally {
                    if (fileInputStream != null) {
                        try {
                            fileInputStream.close();
                        } catch (IOException e) {
                            log.error("Failed to close the FileInputStream, file : " + configPath);
                        }
                    }
               }
            }
        }
    
    
        public String getPassword() {
            return password;
        }
    
        public String getServerURL() {
            return serverURL;
        }
    
        public boolean isRemote() {
            return Boolean.valueOf(remote);
        }
    
    
    }
    
    



    You can checkout the complete code from here 
    Step8 : Use maven to build the files. (mvn clean install)

    Go to target directory and copy org.wso2.samples.pwcb-1.0.0.jar file to <carbon_home>/repository/lib directory and start the server. Then you will ask to enter the key store  password. It is "wso2carbon"

    Now you are done.