Saturday, August 27, 2016

Why are human tasks important for your business process?

Business processes can be considered as workflows ranging from a vacation approval process to a pizza ordering process. With WSO2 Business Process Server , you can easily create these workflows by creating your own BPEL processes.  BPEL is a standard to model your web service orchestration and you read more on it in [1] . In simple terms you can create a BPEL process to interact with different web services getting the responses that you need.  However there are scenarios where everything is not based on just sending a request and getting a response. Some business processes require a human touch.

For example if you consider a leave approving process, you need to send your request to probably your HR manager and wait until he/she approves/rejects your request. Your HR manager might do this right on that day or it could be next week. So until this decision is made, you have to hold back on booking your airline tickets for your vacation. Right? Wouldn't it be nice if you just get notified once the HR manager makes a decision?

Ok , so it is important.... but how to implement this?
Well as a developer  if you were to create a solution with above requirements it will not be an easy task. You need to know when a request was sent, need to make sure that the requests are sent to the correct person, need to keep track on when the HR manager approves/rejects it and finally need to let the employee know about the decision that was made. If it was just about calling a web service yeah sure you can model a BPEL process with few WSDLs but now a real user will be interacting in a step.  So how can we add this human interaction to a BPEL process ?  With WSO2 BPS server this is easily done through human tasks.

Does WSO2 BPS Server make it easy?
[2] is a really good blog on what human tasks are and how you can use it and explains the anatomy behind it with respect to WSO2 BPS. I suggest you first go through it. First you need to create your human task based on WS-HumanTask specification [3].  You can easily create it and deploy in WSO2 BPS which is explained in [4]. Once your human task is all set up, now you need a link to add this human task step into your BPEL process. With the use of  WS-BPEL Extension for People (BPEL4People) specification [5]  you could include your human task interaction to your BPEL process.

But now you might think it is a very tedious task to implement those specifications AND worry about the actual business process creation. But since WSO2 BPS comes with implementations of these specifications you only need to worry about creating those artifacts.

Link human tasks to the BPEL process
For example in your BPEL process when you add a bpel4people step, you could add a remote task partner link defining your human task details, so that once this step is reached, a human task will be created in the human task engine, and the BPEL  process will wait until that task is completed.

 <extensionActivity>
                    <b4p:peopleActivity name="TestTASKPeopleActivity"
                                        inputVariable="b4pInput"
                                        outputVariable="b4pOutput"
                                        isSkipable="no">
                        <b4p:remoteTask partnerLink="b4pPartnerLink"
                                        operation="approve"
                                        responseOperation="approvalResponse">
                        </b4p:remoteTask>
                    </b4p:peopleActivity>
                </extensionActivity>

Create Human Tasks in one go
 If you went through [4] you might feel that creating a human task is a bit of hectic process where you need to create all those files manually. But with WSO2 BPS 3.6.0 that is not the case! Now we have introduced  BPS tooling where you can create your human task in one go and it is really easy. You could check out the basics of this in [6].

Finally now you need to decide how you are going to create the UI for those human tasks?  You can easily create your own API with the admin services that are exposed through WSO2 BPS. Go through [7] for a good explanation on this.


[1] http://wso2.com/library/articles/writing-simple-ws-bpel-process-wso2-bps-apache-ode/
[2]http://wso2.com/library/articles/2012/01/human-tasks-bridging-bits-real-world/
[3] http://docs.oasis-open.org/bpel4people/bpel4people-1.1-spec-cd-09.pdf
[4] https://docs.wso2.com/display/BPS360/Writing+a+Human+Task+Artifact
[5] http://docs.oasis-open.org/bpel4people/ws-humantask-1.1-spec-cd-10.pdf
[6] https://codeoutloud.wordpress.com/2016/06/22/creating-a-human-task-artifact-with-wso2-bps-tooling/
[7] http://nandikajayawardana.blogspot.com/2013/05/how-to-implement-your-own-task-ui-on.html

Wednesday, August 3, 2016

Manually create JWKS_URI for public certificates

A JWK is a JSON representation of a cryptographic key.  More details on this can be found in https://tools.ietf.org/html/rfc7517#section-4. Following blog would give out the steps on how you can manually extract modulus and exponent values of a public certificate , in the format expected in this JWKS_URI.

For this example, we will be trying to extract the values from WSO2 Identity Server's public certificate.

1. Find the public keystore .jks file which is located in <WSO2_IS>/repository/resources/security folder. (wso2carbon.jks)

2. Next step is to extract the public certificate from the keystore, and get the RSAPublic Key of it. For all these steps I will be creating a java client which will be using java.security.KeyStore functions.

 FileInputStream file = new FileInputStream("/Desktop/wso2IS/repository/resources/security/wso2carbon.jks");
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            keystore.load(file, "wso2carbon".toCharArray());
            String alias = "wso2carbon";
            // Get certificate of public key
            Certificate cert = keystore.getCertificate(alias);
            // Get public key
            publicKey = (RSAPublicKey) cert.getPublicKey();

3. Now that you have the publicKey extracted, you can get the modulus and exponent values.
 like below.
BigInteger n =  publicKey.getModulus();
BigInterger e =  publicKey.getPublicExponent();


 But in order to add these into JWKS_URI format , as explained in [1], you need to have those integer values, base64url encoded in their bigendian format. So for this following code snippets will be used.
Following function can be called, where bytes represents n.toByteArray() and e.toByteArray() accordingly.
base64Encode(bytes, 0, bytes.length, false);
So you could invoke like below.

base64Encode(n.toByteArray(), 0 , n.toByteArray().length,false);
base64Encode(e.toByteArray(), 0 , e.toByteArray().length,false);

 this base64Encode function code will be like below.

 public String base64Encode(final byte[] bytes, final int offset, final int length, final boolean padding) {
        final StringBuilder buffer = new StringBuilder(length * 3);
        for (int i = offset; i < offset + length; i += 3) {

            int p0 = bytes[i] & 0xFC;
            p0 >>= 2;

            int p1 = bytes[i] & 0x03;
            p1 <<= 4;

            int p2;
            int p3;
            if (i + 1 < offset + length) {
                p2 = bytes[i + 1] & 0xF0;
                p2 >>= 4;
                p3 = bytes[i + 1] & 0x0F;
                p3 <<= 2;
            } else {
                p2 = 0;
                p3 = 0;
            }
            int p4;
            int p5;
            if (i + 2 < offset + length) {
                p4 = bytes[i + 2] & 0xC0;
                p4 >>= 6;
                p5 = bytes[i + 2] & 0x3F;
            } else {
                p4 = 0;
                p5 = 0;
            }

            if (i + 2 < offset + length) {
                buffer.append(ENCODE_MAP[p0]);
                buffer.append(ENCODE_MAP[p1 | p2]);
                buffer.append(ENCODE_MAP[p3 | p4]);
                buffer.append(ENCODE_MAP[p5]);
            } else if (i + 1 < offset + length) {
                buffer.append(ENCODE_MAP[p0]);
                buffer.append(ENCODE_MAP[p1 | p2]);
                buffer.append(ENCODE_MAP[p3]);
                if (padding) {
                    buffer.append('=');
                }
            } else {
                buffer.append(ENCODE_MAP[p0]);
                buffer.append(ENCODE_MAP[p1 | p2]);
                if (padding) {
                    buffer.append("==");
                }
            }
        }
        return buffer.toString();
    }
This code block will convert the exponent and modulus values to their big endian format, and finally encode them. ENCODE_MAP value will be "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".toCharArray();

After you get these value in proper format, you can look into [1] and create the json representation as required.

[1] https://tools.ietf.org/html/rfc7517#section-4.