Digest based Single-Sign-On
Problem this snippet solves: Sometimes, you are asked to implement some unusual Single Sign On methods. This code helps to deal with Digest based SSO when configured. This specific implementation su...
Updated Jun 06, 2023
Version 2.0Yann_Desmarest
Cirrus
Joined September 11, 2012
Chun_Kit_Cheng
Jul 27, 2018Employee
1/ The server nonce value might contain equal sign so the above code will chop it off in an unintended way.
2/ It would need a condition block in HTTP_REQUEST to identify if it is a request from HTTP::retry.
when RULE_INIT {
set static::user "testuser"
set static::password "testpass"
set static::client_nonce "389db6597243daf2"
set static::nonce_count "00000001"
}
when CLIENT_ACCEPTED {
set retried 0
}
when HTTP_REQUEST {
if { ${retried} == 0 } {
set vars required for Digest SSO
set uri [HTTP::uri]
set method [HTTP::method]
set retried 0
insert a dummy text. Help to inject Digest SSO
HTTP::header replace Authorization "irule-test-digest-sso"
set request [HTTP::request]
HTTP::header remove Authorization
}
}
when HTTP_RESPONSE {
if { [HTTP::status] contains "401" and [HTTP::header exists "WWW-Authenticate"] and [HTTP::header "WWW-Authenticate"] contains "Digest" and $retried == 0 } {
set www_auth [HTTP::header "WWW-Authenticate"]
basically chop the "realm=" and "nonce=" using strictly string functions
set realm [string range ${www_auth} [expr {[string first "realm=" ${www_auth}] + 7}] [expr {[string first "," ${www_auth} [string first "realm=" ${www_auth}]] - 2}]]
set nonce [string range ${www_auth} [expr {[string first "nonce=" ${www_auth}] + 7}] [expr {[string first "," ${www_auth} [string first "nonce=" ${www_auth}]] - 2}]]
retrieve username and password from wherever you want. Can be APM, Basic authentication, ...
binary scan [md5 "$static::user:$realm:$static::password"] H* ha1
binary scan [md5 "$method:$uri"] H* ha2
binary scan [md5 "$ha1:$nonce:$static::nonce_count:$static::client_nonce:auth:$ha2"] H* response
set retried 1
set auth_value "Digest username=\"$static::user\", realm=\"$realm\", nonce=\"$nonce\", uri=\"$uri\", algorithm=MD5, response=\"$response\", qop=auth, nc=$static::nonce_count, cnonce=\"$static::client_nonce\""
insert Authorization header with Digest
set updated_request [string map [list "irule-test-digest-sso" "$auth_value"] $request]
resend the request with the Authorization header filled
HTTP::retry $updated_request
} else {
set retried 0
}
}
Hopefully this would help someone working on this trick.