Managing users and roles with WSO2 Identity Server open API

WSO2 Identity Server enables you to manage users and roles in your system with it's open web services API - so, any third party application can consume this API to handle authentication and authenrization with WSO2 Identity Server.

Following code sample illustrates following tasks and you can download the complete Eclipse project for the sample from here.

1. Authenticates a user
2. Creates a new role
3. Creates a user and add the user to a new role
4. Adds a value to a predefined custom attribute under the user profile
5. Checks whether a given user belongs to a given role.

Please unzip the attached zipped file and import it to Eclipse.

You need to have following in your classpath.

axiom-1.2.9.wso2v1.jar
axis2-1.6.0.wso2v1.jar
commons-codec-1.3.0.wso2v1.jar
commons-fileupload-1.2.0.wso2v1.jar
commons-httpclient-3.1.0.wso2v1.jar
httpcore-4.1.0.alpha1-wso2v1.jar
neethi-2.0.4.wso2v1.jar
org.wso2.carbon.authenticator.proxy-3.0.0.jar
org.wso2.carbon.logging-3.0.0.jar
org.wso2.carbon.um.ws.api-3.0.0.jar
org.wso2.carbon.user.core-3.0.0.jar
wsdl4j-1.6.2.wso2v1.jar
XmlSchema-1.4.6.wso2v1.jar

Please find all these jars inside [IS_HOME]\repository\components\plugins.
package org.wso2.identity.um.sample;

import java.util.HashMap;
import java.util.Map;

import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.wso2.carbon.authenticator.proxy.AuthenticationAdminStub;
import org.wso2.carbon.um.ws.api.WSRealmBuilder;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.UserStoreManager;

public class IdentityServerClient {

 // ONE TIME TASKS WE NEED TO DO BEFORE EXECUTING THIS PROGRAM.

 // TASK - 1 , CREATE a LoginOnly role from IS UI Console
 // ===========================================================
 // 0. Login as admin/admin
 // 1. Go to Users and Roles
 // 2. Click on Roles
 // 3. Add New Role
 // 4. Role Name : loginOnly [please use this name, since it's referred within the code below]
 // 5. Click Next
 // 6. Select only the 'Login' permission
 // 7. Click Next
 // 8. No need to select any users
 // 9. Click Finish

 // TASK - 2 , CREATE a custom claim from IS UI Console
 // ===========================================================
 // 0. Login as admin/admin
 // 1. Go to Claim Management
 // 2. Click on http://wso2.org/claims
 // 3. Click on 'Add New Claim Mapping'
 // 3.1 Display Name : Business Phone
 // 3.2 Description : Business Phone
 // 3.3 Claim Uri : http://wso2.org/claims/businessphone
 // 3.4 Mapped Attribute : http://wso2.org/claims/businessphone
 // 3.5 Support by default : Checked
 // 3.6 The rest can be kept blank

 private final static String SERVER_URL = "https://localhost:9443/services/";
 private final static String APP_ID = "myapp";

 /**
  * @param args
  */
 public static void main(String[] args) {

  AuthenticationAdminStub authstub = null;
  ConfigurationContext configContext = null;
  String cookie = null;
  String newUser = "prabath2";

  System.setProperty("javax.net.ssl.trustStore", "wso2carbon.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");

  try {
   configContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(
     "repo", "repo/conf/client.axis2.xml");
   authstub = new AuthenticationAdminStub(configContext, SERVER_URL
     + "AuthenticationAdmin");

   // Authenticates as a user having rights to add users.
   if (authstub.login("admin", "admin", APP_ID)) {
    cookie = (String) authstub._getServiceClient().getServiceContext().getProperty(
      HTTPConstants.COOKIE_STRING);

    UserRealm realm = WSRealmBuilder.createWSRealm(SERVER_URL, cookie, configContext);
    UserStoreManager storeManager = realm.getUserStoreManager();

    // Add a new role - with no users - with APP_ID as the role name

    if (!storeManager.isExistingRole(APP_ID)) {

     storeManager.addRole(APP_ID, null, null);
     System.out.println("The role added successfully to the system");
    } else {
     System.out.println("The role trying to add - already there in the system");
    }

    if (!storeManager.isExistingUser(newUser)) {
     // Let's the this user to APP_ID role we just created.

     // First let's create claims for users.
     // If you are using a claim that does not exist in default IS instance,
     Map claims = new HashMap();

     // TASK-1 and TASK-2 should be completed by now.
     // Here I am using an already existing claim
     claims.put("http://wso2.org/claims/businessphone", "0112842302");

     // Here we pass null for the profile - so it will use the default profile.
     storeManager.addUser(newUser, "password", new String[] { APP_ID, "loginOnly" },
       claims, null);
     System.out.println("The use added successfully to the system");
    } else {
     System.out.println("The user trying to add - already there in the system");
    }

    // Now let's see the given user [newUser] belongs to the role APP_ID.
    String[] userRoles = storeManager.getRoleListOfUser(newUser);
    boolean found = false;

    if (userRoles != null) {
     for (int i = 0; i < userRoles.length; i++) {
      if (APP_ID.equals(userRoles[i])) {
       found = true;
       System.out.println("The user is in the required role");
       break;
      }
     }
    }
    
    if (!found){
     System.out.println("The user is NOT in the required role");
    }
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

Using 'Sign in with Twitter' ??? Read this then - You may be NOT safe



There are many application enabled for 'Sign in with Twiiter'.

http://www.twitpic.com/, http://micromobs.com/ are few to name.

Once you click on 'Sign in with Twiiter' - you are redirected to http://twitter.com/oauth/authorize page following the OAuth protocol, where you need to authorize access to the particular relying party application.

By this time, if you haven't logged in to Twitter directly, then you are asked to enter Twitter credentials as well.

These credentials are passed over the wire in clear text.

Following, I captured using Wireshark - there you can see the username and twitter password in clear text. [ I have replaced my original password with XXXXX]

authenticity_token=833dc4385cf064eea29a2ae9faddbc4ae3903659&oauth_token=O1K0VwKaFBJMDYA9f7qr53D6tqLNj4WBFmMmCONnmkI&session%5Busername_or_email%5D=prabath&session%5Bpassword%5D=XXXXX

But, when you directly login to Twitter through http://twitter.com/login - there it uses HTTPS - so you are safe.

So - if you are using 'Sign in with Twitter' - anywhere, I would rather recommend you login to Twitter directly via http://twitter.com/login and then click on 'Sign in with Twitter' link on the corresponding web site. Then you are not asked to authenticate again - only you need to do is Allow or Deny.

WS-Trust with Fresh Banana Service

This blog post explains the interactions of an STS client with an STS.

STS stands for Security Token Service.

What does an STS do ?

A security token service [STS] implements the protocol defined as per the WS-Trust specification.

WS-Trust specification defines message formats and message exchange patterns for; issuing, renewing, canceling and validating security tokens.

A given security token service provides one or more of these capabilities.

So - the client interacts with the STS - to get done any of the above functionalities, that is, issuing, renewing, canceling and validating security tokens.

In fact - why the client needs a security token...?

Client needs a security token - because it needs to access a service which requires a security token issued from a specific token issuer [STS].

Client can access the service, only if - client provides the security token issued from the specified token provider.

I guess - now we are clear about, what does an STS do and why does a client need a security token.

Wait a minute... still we don't know what is meant by the 'security token' ?

A security token is an XML payload - as requested by the relying party service.

If it is a SAML token then it represents a collection of claims in the form of Assertions.....

A claim is a statement made about a client, service or other resource (e.g. name, identity, key, group, privilege, capability, etc.)....

The service can say, in its service policy - what claims it requires... so, the client has to have those in the security token.

For example, the service can say - "if you want to access me, you should have your First Name, Last Name and the Age in the security token - if NOT don't even think about me.."

Now - we know what a security token is - it is issued by the STS, with the claims required by the service.

Before we dig in to further details - let's listen to a discussion between - the client, service and the STS.



Client / Service

Client : "Hey I want to access your Fresh-Banana service.."

Service: "Are you nuts.. Where is your security token..?"

Client: "Poh... you've gone mad - anyway tell me from where you want me to bring the token..."



Service: "Heh.. heh.. I know you from good old days - you never lied me.. ha :D - never expect to trust you again.. :P Bring the token from your Master if you want to have a Fresh-Banana, else - hmmm... you know what to do.. ;) '

Client: "Catch you later.. now tell me what you want to have in the security token.."

Service: "You got to have your Name and Age - we don't issue Fresh Banana's for baby monkeys..LOL :)"


Client / STS

Client: 'Hey man.. I need a token to access Fresh-Banana service - I know you can do it - can I have one...?'

STS: 'You got to be kidding.. I don't issue security tokens to monkeys I never know... "




Client: "Check this out man [monkey wags its tail]... I am your monkey..."

STS: "That looks fine.. Here's your token... this is valid only for 2 days..."

Client: "Thanks buddy.. you are quite smart ;) "


Client / Service

Client: "Hey man... I am back with the token... Give me my fresh banana .... Can't waste anymore time..."

Service: "Ho...ho... looks like token is fine.. enjoy the Fresh Banana..."




I guess, the above explains the information flow between the three parties involved in the trust relationship - at a very high-level.
Now, let's dig in to the interaction between the client and the STS - the rest we'll look in to in a future blog post.

Security token service[Monkey man] issues tokens only for client [The Monkey] it trusts.

Trust relationship between the client and the STS can be established via user name/password or certificates or via any other mean defined by the STS [Monkey was able to prove itself to the monkey man]

STS communicates this [the form of trust relationship] via its security policy as per WS-Security Policy.

For example, STS can enforce all its clients to sign the Request for the Security Token [RST] - or else - prove themselves via UsernameToken [that is user name / password].

The bottom line is - STS knows the client well and it knows how to authenticate the client.

As the first step - the client prepares the RST [ this is how we call the Request - under the terminology defined in WS-Trust spec] - and sends a web service request, secured to be compliant with the security policy of the STS.

This RST also includes the required claims for the response - or the security token.

What else the RST includes?

- The end point reference [EPR] of the service, where the client goes to use this token
- The desired valid time for the expecting security token
- Token type of the expecting security token [ SAML 1.1 / SAML 2.0]
- and more...

Lets discuss a simple flow between the client and the STS - without being bound to any heavy technical jargons - defined in the spec.

Once client sends the RST to the STS - STS will first validate the authenticity of the requester - by validating the request against the defined security policy of STS.

Then it will start preparing the security token [Request Security Token Response].

STS will first include all the requested claims - and will sign it with its private key .

Then - it finds the public certificate of the service which this token will be sent by the client and will encrypt the token with it.

Now, this security token is opaque to the requester - or the client - since it's encrypted with service's public key.

But - still the client needs to know way to refer to that token.
For - example, if client wants to cancel or renew the token, the it has to know which token its referring to.

To help the client with the above, STS adds two extra elements to the RSTR - which are visible to the client.

These elements are known as RequestedAttachedReference and RequestedUnattachedReference.

If client wants to refer the token within the SOAP message it self - the it will use the id from RequestedAttachedReference - if it wants to refer the token of the message itself, then it will be the RequestedUnattachedReference.

For example, when issuing a token, the STS caches the issued token in its side. So - if the client wants to Renew the token, then this can be done by client sending the id from the RequestedUnattachedReference to the STS.

Apart from the above - STS also adds another element called, Proof-of-Possession Token.

A proof-of-possession (POP) token is a security token that contains secret data that can be used to demonstrate authorized use of an associated security token..

The POP token is visible to the requester.

Proof of possession is needed when the client does not provide the public key to use and signs (authenticates) this using the corresponding private key, thereby proving possession.

Further, the STS includes a KeyInfo element in to Security Token, that can be used to validate the proof of possession token. This element is only visible to the relying party service.

Now, the STS will send the encrypted token to client.
This approach we discussed is known as Holder of Key approach - we'll discuss the other approaches in a future post.

[Thanks a lot Chanaka for the images...]