Consuming a REST Sevice with Digest Authenctication
Hi guys,
I'm trying to consume a REST Service that use Digest authentication, I'm trying to implement the authentication but I'm don't know where is my mistake.
Someone have already used this type of authentication.
Below the code I wrote to try to generate the response hash:
//
// Test data:
// Do TestDigest^HC.Debug("posstman", "password", "/digest-auth", "postman-echo.com", 80)
// Do TestDigest^HC.Debug("usr", "pwd", "/digest-auth/auth/usuario/senha/MD5", "httpbin.org", 80)
TestDigest(username, password, url, server, port) Public
{
Set httpRequest = ##Class(%Net.HttpRequest).%New()
Set httpRequest.Server = server
Set httpRequest.Port = port
Set statusCode = httpRequest.Send("GET", url)
If ($System.Status.IsError(statusCode))
{
Do $System.Status.DisplayError(statusCode)
}
Set authenticationData = httpRequest.HttpResponse.GetHeader("WWW-AUTHENTICATE")
Write !, "WWW-AUTHENTICATE: ", authenticationData, !
Set qop = $$GetHeaderVar(authenticationData, "qop")
Set nonce = $$GetHeaderVar(authenticationData, "nonce")
Set realm = $$GetHeaderVar(authenticationData, "realm")
Set algorithm = $$GetHeaderVar(authenticationData, "algorithm")
Set nc = "00000001"
Set cnonce = $$HashValue($Horolog, 1)
Set hA1 = $$HashValue(username _ ":" _ realm _ ":" _ password)
If ($ZConvert(algorithm, "U") = "MD5-SESS")
{
Set hA1 = $$HashValue(hA1 _ ":" _ nonce _ ":" _ cnonce)
}
Set hA2 = $$HashValue("GET:" _ url)
If (qop '= "")
{
Set response = $$HashValue(hA1 _ ":" _ nonce _ ":" _ nc _ ":" _ cnonce _ ":" _ qop _ ":" _ hA2)
}
Else
{
Set response = $$HashValue(hA1 _ ":" _ nonce _ ":" _ hA2)
}
Set digestResponse = "Digest username=""*"",realm=""*"",nonce=""*"",uri=""*"",response=""*"",algorithm=""*"",qop=*,nc=*,cnonce=""*"""
Set digestResponse = $Replace(digestResponse, "*", username, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", realm, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", nonce, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", url, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", response, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", algorithm, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", qop, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", nc, 1, 1)
Set digestResponse = $Replace(digestResponse, "*", cnonce, 1, 1)
//
Write !,"Authorization: ", digestResponse, !, !
//
Do httpRequest.SetHeader("Authorization", digestResponse)
//
Set statusCode = httpRequest.Send("GET", url)
If ($System.Status.IsError(statusCode))
{
Do $System.Status.DisplayError(statusCode)
}
Do httpRequest.HttpResponse.OutputToDevice()
}
HashValue(value) Public
{
Return $ZConvert(##Class(%xsd.hexBinary).LogicalToXSD($System.Encryption.MD5Hash(value)), "L")
}
{
Return $ZConvert(##Class(%xsd.hexBinary).LogicalToXSD($System.Encryption.MD5Hash(value)), "L")
}
GetHeaderVar(header, varName) Public
{
Set listVars = $ListFromString(header, ",")
For index = 1 : 1 : $ListLength(listVars)
{
Set value = $List(listVars, index)
If ($ZConvert(value, "U") [ $ZConvert(varName, "U"))
{
Return $Translate($Piece(value, "=", 2), """", "")
}
}
Return ""
}
{
Set listVars = $ListFromString(header, ",")
For index = 1 : 1 : $ListLength(listVars)
{
Set value = $List(listVars, index)
If ($ZConvert(value, "U") [ $ZConvert(varName, "U"))
{
Return $Translate($Piece(value, "=", 2), """", "")
}
}
Return ""
}
Hi Cristiano,
With some small changes, your code works for me:
Your comments on how to test should read:
/// Do TestDigest^HC.Debug("usuario", "senha", "/digest-auth/auth/usuario/senha/MD5", "httpbin.org", 80)
Change the line:
To:
After this line:
Add the following code:
Set opaque = $$GetHeaderVar(authenticationData, "opaque")
If opaque '= ""
{
Set digestResponse = digestResponse _ ",opaque=""" _ opaque _ """"
}
Hope this helps!
Thanks Navarro,
I don't see the typo in te test data, and with the change of the cnonce calculation works like a charm.
For my specific case, the service doesn't send de opaque, but I changed the code to support the opaque too.
Abraço.