Tuesday, 16 September 2014

Handling HTTPS (one-way SSL) requests in ADF Mobile

This usecase shows how ADF Mobile applications can be configured to handle one-way SSL.
The service runs on weblogic server, in which one way SSL has been enabled.
The weblogic server has been configured to use custom identity and custom trust. I have referred to the post to do this. Its a very good post and gives in-depth details about the various steps. To give a complete idea w.r.t mobile, I have just consolidated the commands and put them under the Server End section.

JDeveloper with Mobile Application Framework installed; Weblogic server.

Server End:
1) Create a folder in any location, say Desktop. Let us call the folder ServerCerts.
Next, open a terminal from <MW_HOME>\jdeveloper\system12.1......\DefaultDomain\bin.
Run the command setDomainEnv.cmd. (assuming that you are using Jdeveloper on a windows system).
2) From the same terminal, cd and navigate to the newly created folder. Run the below command:
java utils.CertGen -certfile ServerCert -keyfile ServerKey -keyfilepass keypass -cn <<IP or hostname>>

This will generate a public certificate as well as a private key for you. The common name that you give here will be the common name in the certificate. So, ensure that the common name matches with the server's hostname. In case your server's hostname is localhost or, provide the system IP as the common name. 

3) Copy CertGenCA manually from <<MW_HOME>>\wlserver\server\lib to the folder ServerCerts. Run the below two commands:
java utils.der2pem CertGenCA.der

type serverCert.pem CertGenCA.pem >> myCert.pem

Since we used CertGen to generate our public-private key pair, it would have been signed by the certifying authority CertGenCA. Thus, we need to append the public certificate of this certifying authority to our public certificate. Using the first command, we convert the format of the CerGenCA certificate to der format. Next, we append it to the public certificate and create a new pem certificate, called myCert.pem. If you look inside myCert.pem, you will be able to see two certificates, one is the server's certificate, and the other is that of CertGenCA's. To take a look, use
keytool -printcert -file myCert.pem

myCert.pem is the file that we will be using at the mobile end, to establish trust.

4)  Weblogic requires jks or kss formats for keystores. Thus, we add the private key and public certificate to a jks keystore using the below command.
java utils.ImportPrivateKey -keystore  SeverIdentity.jks -storepass storepass -storetype JKS -keypass keypass -alias mykey -certfile myCert.pem -keyfile ServerKey.pem -keyfilepass keypass

ServerIdentity.jks will now have the private certificate as well as the public certificate along with the CA’s public certificate. The identity keystore for the server is now ready. For the server truststore, we will use DemoTrust.jks, which comes by default with weblogic. Copy DemoTrust.jks from <<MW_HOME>>\wlserver\server\lib to myCert folder.

5) Go to <<MW_HOME>>\jdeveloper\system12....\DefaultDomain (or the relevant domain location, if it is standalone). Paste ServerIdentity.jks and the DemoTrust.jks files here. Now, start weblogic server and go to weblogic console in the browser. Navigate to Servers->DefaultServer. Under Keystores tab, change the Keystores to Custom Identity and Custom Trust. Set the below details:
Custom Identity Keystore:SeverIdentity.jks
Custom Identity Keystore Type:JKS
Custom Identity Keystore Passphrase: Storepass

Custom Trust Keystore:DemoTrust.jks
Custom Identity Keystore Type:JKS
Custom Identity Keystore Passphrase: DemoTrustKeyStorePassPhrase

Go to the SSL tab
Private Key Alias: mykey
Private Key Passphrase: keypass

In the same tab, go to Advanced, and set Hostname verification to None. Set Two Way Client Cert Behavior: Client Certs Requested But Not Enforced. 
Save all and restart the server. Run the REST service. Access it using https url and port in the browser, and verify the certificate. 

Mobile End: 
1) Create a new ADF Mobile application.
2) Expand Application Resources -> Resources -> Security. You will find cacerts file there. Copy the location of this file using Edit -> Copy Path. The default password for cacerts is 'changeit'. 
3) From the terminal, run the below command:
keytool -import -v trustcacerts -alias mykey -file "location of myCert.pem" -keystore <<location of cacerts>> -keystore changeit -storepass changeit

For e.g., in my case the command looked as below:

keytool -import -v -trustcacerts -alias mykey -file "Desktop\ServerCerts\myCert.pem" -keystore jdev_home\jdeveloper\mywork\SSLApp\resources\security\cacerts -keypass changeit -storepass changeit

When prompted to trust the certificate, say yes. On successful run of the command, you will be able to see the line in the terminal.

Certificate was added to keystore
[Storing jdev_home\jdeveloper\mywork\SSLApp\resources\security\cacerts]

The server's public certificate has now been added to cacerts. Create Data Control for the REST service and design the pages. Deploy to the emulator.
Your application should be able to trust the server and render the web service data.

If you are redirecting your HTTP requests through HTTP analyzer, or some other tool, you may end up with 'certificate issued by unrecognized entity' error. This is because cacert would require the certificate of the analyzer as well. So, its better to switch off packet sniffing in SSL cases. :)