Digest Authentication

Introduction

API Fortress can handle nearly any authorization scheme. Below, we provide a guide on how to deal with digest authentication. Digest authentication is a method of authentication in which a request from a potential user is received by a network server and then sent to a domain controller. The domain controller sends a special key, called a digest session key, to the server that received the original request. The user must then produce a response, which is encrypted and transmitted to the server. If the user’s response is of the correct form, the server grants the user access to the network, Web site or requested resources for a single session.

Digest Authentication Workflow

**NOTE: this authentication workflow will only work self-hosted/on-premises version of API Fortress**

  1. Make a call to the API requiring digest authentication (note that this initial call will fail so make sure to set expect values in API Fortress)
  2. Grab and use the “WWW-Authenticate” header from the failed response to create a md5 hashed response to authenticate yourself.
  3. Using the “variable” component in “Language” (Groovy) mode, create your md5 hashed response.
  4. Using the “variable” component create the appropriate header value.
  5. Make the API call requiring digest authentication again, this time using an “Authentication” header with the value created in the previous step. You will now be able to access the API.

An example of this can be found below, to test this out yourself copy and paste the code into an API Fortress test.

    <set var="uri" value="/digest-auth" lang="java"/>
<set var="username" value="postman" lang="java"/>
<set var="password" value="password" lang="java"/>
<get url="https://postman-echo.com${uri}" params="[:]" var="data" mode="text" expect="401|VALID">
</get>
<set var="auth" lang="java">
<![CDATA[def du = org.apache.commons.codec.digest.DigestUtils
String stripValue(String str) {
str = str.substring(str.indexOf('"')+1)
str = str.substring(0,str.indexOf('"'))
str
}
def tokens = data_response.headers['WWW-Authenticate'].split(',')
def realm = stripValue( tokens.find{it -> it.trim().contains('realm')} )
def nonce = stripValue( tokens.find{it -> it.trim().contains('nonce')} )
def qop = stripValue( tokens.find{it -> it.trim().contains('qop')} )
def A1 = du.md5Hex("${username}:${realm}:${password}")
def A2 = du.md5Hex("GET:${uri}")
def digest = du.md5Hex("${A1}:${nonce}:${A2}")
return [realm:realm,nonce:nonce,digest:digest]]]>
</set>
<comment>
<![CDATA[${auth}]]>
</comment>
<set var="header" value="Digest username=\&quot;postman\&quot;, realm=\&quot;Users\&quot;, nonce=\&quot;${auth.nonce}\&quot;, uri=\&quot;/digest-auth\&quot;, response=\&quot;${auth.digest}\&quot;" lang="java"/>
<get url="https://postman-echo.com${uri}" params="[:]" var="payload" mode="json">
<header name="Authorization" value="${header}"/>
</get>
<comment>
<![CDATA[${payload}]]>
</comment>