Search This Blog

Saturday, February 22, 2014

ColdFusion: Implement Authentication for Web Services Using SOAP Header

The following script demonstrates how to implement authentication in SOAP header using ColdFusion.
We could pass username and password in simple value, but in this example we wanted to deliver them in XML.

NOTE: This blog has been updated with new code. The original one was written two years ago. :)

WebService.cfc

<cfcomponent output="false" hint="An example of Web Service.">

  <cffunction name="echo" output="false" access="remote" returntype="string" hint="Accept text/string; and return it back to the caller.">
    <cfargument name="message" type="string" required="false" default="" />
    
    <cfset var response = "It is NOT a SOAP request." />
    <cfset var namespace = "http://localhost/test/soap/" />

    <!--- Check if it is a SOAP request and the request is legit --->
    <cfif isSOAPRequest() AND authenticateRequest()>
      <cfset response = "It is a SOAP request. Echoes: " & arguments.message />
    </cfif>

    <cfreturn response />
  </cffunction>

  <cffunction name="authenticateRequest" output="false" access="private" returntype="boolean" hint="Authenticate request.">
    <cfset var result = false />
    <cfset var namespace = "http://localhost/test/soap/" />

    <!--- Get authentication node and return it as an XML --->
    <cfset var auth_node = getSOAPRequestHeader(namespace, "authentication", true) />

    <!--- Parse the authentication node content, which is credential --->
    <cfset var cred_node = xmlParse(auth_node.xmlRoot.xmlText) />

    <!--- Get the data from the XML --->
    <cfset var username = cred_node.xmlRoot["username"].xmlText />
    <cfset var password = cred_node.xmlRoot["password"].xmlText />   

    <!--- Verify the username and password --->
    <cfif NOT compare("jsmith", username) AND NOT compare("abc123", password)>
      <cfset result = true />

    </cfif>

    <cfreturn result />
  </cffunction>

</cfcomponent>

client.cfm

<!--- Settings --->
<cfset end_point = "http://localhost/test/soap/WebService.cfc?WSDL" />
<cfset ws_args = {refreshwsdl=true} /> <!--- Force ColdFusion to refresh WSDL stub --->

<!--- Create Web service object --->
<cfset web_service = createObject("webService", end_point, ws_args) />

<!--- Construct XML document, which contains username and password --->
<cfxml variable="xml_doc">
  <credential>
    <username>jsmith</username>
    <password>abc123</password>
  </credential>
</cfxml>

<cfset namespace = "http://localhost/test/soap/" />

<!--- Add credential in the header --->
<cfset addSOAPRequestHeader(web_service, namespace, "authentication", toString(xml_doc)) />

<!--- Add SOAPAction:"" in the header --->
<!--- The header field value of empty string ("") means that the intent of the SOAP message is provided by the HTTP Request-URI. 
  No value means that there is no indication of the intent of the message. 
  Reference: http://www.w3.org/TR/2000/NOTE-SOAP-20000508/ --->
<cfset addSOAPRequestHeader(web_service, namespace, "SOAPAction", chr(34) & chr(34)) /> <!--- The value can be empty --->

<cfset message = "Hello, there!">
  
<!--- Invoke the service --->
<cfset response = web_service.advancedEcho(message) />

<!--- Get the response in SOAP --->
<cfdump var="#getSOAPResponse(web_service)#" />

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.