Skip to main content

WSS Security in Android using Ksoap2 SOAP Library


In this post, we are going to implement the WSS security in android using KSOAP2 library. Generally, most of the android application is created on the REST-based API but still, there are lots of android application which are created on the SOAP protocol and if you are here then obviously you have a project which required SOAP-based implementation directly from android app and implementing the security in this is very important. So let's start the implement WSS Security in Android using Ksoap2 SOAP Client.





Create SOAP Demo Android Project





To complete learn the implementation of WSS security, first of all, we have will create an android project. So Let's create the project using the Android Studio IDE File->New Project and select the Activity type and type the name of your project and click the finish button.





UI Design of the SOAP Android Application





Designing the Layout of any application is the first and most important part of any application. So we are going to design the layout of our application because I personally thought that if something looks good then it can be sold easily. But here we are not going to invest much time on the UI design we are just taking the username and password as input and sending them to the API server after creating the required header and body, which most difficult part of the calling the WSS secure web service API from android.





Android KSOAP2 SOAP WSS security  project input layout
KSOAP2 to Call the WSS secure SOAP API




Creating a Header of the SOAP Request





Header creation of the SOAP request is the most important part of the implementation of the WSS security in the Android application. Its include the below some important part on which we will come step by step.





  • Username token creation
  • Nonce creation
  • Creating the Password Digest for the soap call




Below is our code to generate our WSS header along with the nonce, created and digest.





import android.util.Base64
import android.util.Log

import org.kxml2.kdom.Element
import org.kxml2.kdom.Node

import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.security.SecureRandom
import java.text.SimpleDateFormat
import java.util.Date
import java.util.TimeZone

class WsseToken(
private val user: User?) {
private val nonce: String
private val createdAt: String
private val digest: String?

val wsseHeader: String
get() {
val header = StringBuilder()
header.append("UsernameToken Username=\"")
header.append(this.user?.username)
header.append("\", PasswordDigest=\"")
header.append(this.digest)
header.append("\", Nonce=\"")
header.append(Base64.encodeToString(this.nonce.toByteArray(), Base64.NO_WRAP))
header.append("\", Created=\"")
header.append(this.createdAt)
header.append("\"")
return header.toString()
}


init {
this.createdAt = generateTimestamp()
this.nonce = generateNonce()
this.digest = generateDigest()
}//we need the user object because we need his username

private fun generateNonce(): String {
val random = SecureRandom()
val seed = random.generateSeed(10)
return bytesToHex(seed)
}

private fun generateTimestamp(): String {
sdf.timeZone = TimeZone.getTimeZone("UTC")

return sdf.format(Date())
}

private fun generateDigest(): String? {
var digest: String? = null
try {
val md = MessageDigest.getInstance("SHA-1")
val sb = StringBuilder()
sb.append(this.nonce)
sb.append(this.createdAt)
sb.append(this.user?.password)
val sha = md.digest(sb.toString().toByteArray())
digest = Base64.encodeToString(sha, Base64.NO_WRAP)
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
}

return digest
}

companion object {
val HEADER_AUTHORIZATION = "Authorization"
val HEADER_WSSE = "X-WSSE"

private val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

fun bytesToHex(bytes: ByteArray): String {
val hexArray = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')
val hexChars = CharArray(bytes.size * 2)
var v: Int
for (j in bytes.indices) {
v = bytes[j].toInt() and 0xFF
hexChars[j * 2] = hexArray[v.ushr(4)]
hexChars[j * 2 + 1] = hexArray[v and 0x0F]
}
return String(hexChars)
}
}
}




For this, you need to download the KSOAP2 library which you can download from the below here and add it as the library to your project.





Download and add KSOAP2 jar as a library to your project





There are two methods to add the KSOAP2 library to your project. You can choose the method which is based suited for your project.





Add KSOAP2 library using the Gradle package





First, add the maven repository https://oss.sonatype.org/content/repositories/ksoap2-android-releases/ to your project level gradle.properties files as given below.






allprojects {
repositories {
google()
jcenter()
maven { url 'https://oss.sonatype.org/content/repositories/ksoap2-android-releases/' }

}
}




Then add the library to your app level build.gradle properties and sync the project.





implementation 'com.google.code.ksoap2-android:ksoap2-android:3.6.4'




Adding KSOAP2 jar to your project





If the first method does not work due to any reason then you can add the KSOAP2 jar directly to your project. Download the KSOAP2 library from the repository here.





Add KSOAP2 as library to your android studio project.

After downloading the jar copy it to the project library folder and by right-clicking on the lib folder.





Once the file is copied in the lib folder of your project just right click on the jar and click on add as library.






If somehow you are not able to add as library option after right click then you can add it by adding the below line into your build.gradle properties files of the project.





 implementation files('libs/ksoap2-android-assembly-3.6.4-jar-with-dependencies.jar')




Create the Request Envelope of the SOAP request





For creating the envelope of the request we need to create the instance of the previously created class WsseToken.





 private fun soapSerializationEnvelope(user: User?): SoapSerializationEnvelope {
val rawEnvelope = SoapSerializationEnvelope(SoapEnvelope.VER11)
rawEnvelope.implicitTypes = true
rawEnvelope.isAddAdornments = false
rawEnvelope.dotNet = false
val token = WsseToken(user)
rawEnvelope.headerOut = token.xmlHeader
return rawEnvelope
}




In the above code block, we are creating the token component by passing the user as an object. This user object is nothing just a POJO with the username and password that will be used by the WsseToken class to creating the header (nonce, token, created, extra) and taken as input from the end user as described in the start of this post. This method will provide us a raw Envelope that means we need to add the body of our request to this envelope. Our generated header will look like as given below.





<v:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-DA34AE4918361575D615616385228214">
<wsse:Username>myusername</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">v9cBHtgupGarwmkE21ORHjgzMkA=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">QjFEREY0REE0NEQxMDlCNTkyRjQ=</wsse:Nonce>
<wsu:Created>2019-07-13T09:01:21Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</v:Header>




Create the SOAP body and add the WS SOAP method to it





We are done with the header creating the header of SOAP request. Now, we need to create the body part of our soap request. So let's create the body of the request. Our body will look like as given below.





<v:Body>
<n0:getUserInfoRequest>
<n0:username>myusername</n0:username>
<n0:usercode>myusercode</n0:userpin>
</n0:getUserInfoRequest>
</v:Body>




So for creating the body, we need to create an instance of the SoapObject as given below.





val request = SoapObject("namespace", "getUserInfoRequest")




After this, we need to add the properties like username and usercode to the body of the request. Both filed are symbolic here and you can put the value as per your requirement in your request body.





request.addProperty("n0:username", "myusername")
request.addProperty("n0:usercode", "myusercode")




It will create the soap body as given in the above example. Ater this we need to add the soap body to our envelope which we have created earlier.





val requestEnvelope = getRawSoapSerializationEnvelope(user)
requestEnvelope.bodyOut = request
requestEnvelope.setOutputSoapObject(request)




Call the SOAP URL endpoint using KSOAP2





So far we have created our request header and body part of the request which is the main task of the Implement WSS Security in Android using Ksoap2 SOAP Client. Now its time to call our SOAP endpoint using our created request. So, create an instance of HttpTransportSE and call the endpoint URL.





 val t = HttpTransportSE("Here is your exact end point url")
t.call("", requestEnvelope)




If required we can enable the debug mode of the request using below method of the Http call.





 t.debug = true




Make sure to call the above method from some background jobs like because network operators are not allowed on the main threads.





Reading the Request and Response of the HTTP call in Android





If you want to read the request and response that was sent over the HTTP, then you can do as given below.





val requestdump=t.requestDump  
val responsedump=t.t.responseDump




Parsing the response of the HTTP call in android





The default parser of the HTTP response does not work due to the complexity of the response so in that case, you can create your own simple parser.





 fun getFromXmlResponse(XMLResponse: String): Response {
val response = Response()
val `is` = ByteArrayInputStream(StandardCharsets.UTF_8.encode(XMLResponse).array())

val dbFactory = DocumentBuilderFactory.newInstance()
var dBuilder: DocumentBuilder? = null
try {
dBuilder = dbFactory.newDocumentBuilder()
} catch (e: ParserConfigurationException) {
e.printStackTrace()
}

var doc: Document? = null
try {
assert(dBuilder != null)
doc = dBuilder!!.parse(`is`)
} catch (e: IOException) {
e.printStackTrace()
} catch (e: SAXException) {
e.printStackTrace()
}

var element: Element? = null
if (doc != null) {
element = doc.documentElement
}
element?.normalize()
assert(element != null)
val nList2 = element!!.getElementsByTagName("*")
for (i in 0 until nList2.length) {
val node = nList2.item(i)
val element2 = node as Element
if (element2.tagName == response.tagName) // hear response.tagName is tag that you want capture
response.name = element2.textContent
else if (element2.tagName == response.tagLocation)
response.location =element2.textContent
// and so one you can add the value of all tag as per requirment
}

return response
}




In the above XML parser is a very simple method to parse the response you can create your own parser by taking this as reference depending on the requirement. In the above method, the Response is a simple POJO with the required filed to store the value. If we consider the above two filed then it looks like as given below.





class BalanceResponse {
var name: String? = null
var location: String? = null
companion object {
var tagName = "name"
varocation = "location"
}
}




Wrapping up Implement WSS Security in Android using Ksoap2 SOAP Client





If you go through the post step by step then you will find that it's not so much hard, but finding all these stuff is difficult for me and it takes a lot of my time. So Let's Summary what we have done so far.





Create an Android Project if you don't have a working project. After that download the KSOAP2 library and add it as a library in your build.gradle file, create the header, create the body of the request, call the HTTP endpoint and at last parse and show the result. Below is some reference that you can refer get deeper about the WSS security details.





Reference: https://www.oasis-open.org/committees/download.php/13392/wss-v1.1-spec-pr-UsernameTokenProfile-01.htm


Comments

Popular posts from this blog

Flutter How to Start Android Activity from Flutter View

Flutter and Dart is an excellent combination for creating the UI, but for accessing the platform-specific service we need to open platform-specific activity. So lets in this article we will explore how to start an android activity and access the service from Flutter View. Create a Project for this Android Activity Flutter View Demo Create a Project From File menu select the New Flutter Project Enter the project name Select the AndroidX support and click on next After the above, we step click on Finish We will have the following project structure created. Create the Second Activity in Android Just go to the android folder and open it in separate windows. We will have the following project structure. Create the Activity Just right-click on the Kotlin folder and create a blank activity from the menu. If you create the activity then you may be required to upgrade the Gradle and do some import. So Just click on update and wait for the project s

Kotlin Parcelable Array Objects Send To Activity

We know that IPC (Inter Process Communication) between the activity is an extremely important part of any application development. We often required that we need to send some data to other activity. For example, we may be required to send an array of data, data could be an Integer, String, Long, Double, Float or any other custom data objects. So, In this example, we are going to learn how to implement the Kotlin Parcelable Array object to send the data from one activity to second activity. What is Parcel? The parcel class is designed as a high-performance IPC transport. A Parcel can contain both flattened data that will be unflattened on the other side of the IPC, and references to live IBinde r objects that will result in the other side receiving a proxy IBinder connected with the original IBinder in the Parcel. Create Kotlin Parcelable Array Objects Parcelable is API for placing the arbitrary objects into the Parcel. In Actual in android app development, Parcelable is an interface

Scan and List All Available WiFi Network In Android

In this tutorial, we learn how to connect to a WiFi hotspot in android by code. In this Demo we will create an as small app which will scan the all available network or Hotspot and list down the network when you select specific network, the application will connect that particular network. You May Like Below Topic: How to Read and Write JSON data using GSON WP Android App using REST and volley WP Android App using REST and volley part2 Implementation of SwipeRefreshLayout in RecyclerView Create Amazing Bottom Navigation Bar Without Any External Library Introduction In this tutorial, we learn how to connect to a WiFi hotspot in android by code. In this Demo we will create an as small app which will scan the all available network or Hotspot and list down the network when you select specific network, the application will connect that particular network. We will add this functionality to our existing Demo app " Video Gallery ". If you would like to check out t