Digest Authentication
Yennie at aol.com
Yennie at aol.com
Wed Nov 20 00:56:01 EST 2002
I can assure you it's possible... cause I've done it!
I'd have to do some serious editing to post a complete implementation, but
here are a few of the important handlers I came up with. The checkPassword()
handler has been edited heavily from my original code, so it may need some
fixing. Also note that the nonce / opaque values are not implemented ideally
in authenticateHeader(). You'll need a basic understanding of the RFC to make
good use of these.
Hope this helps!
function checkPassword theSocket,requestHeader, at replyHeader, at userName
global server_opaque,server_nonce,nonce_time, loggedInIDs, loggedInNames,
xfactor
put "WebCF Registered Users" into realm -- default
put lineOffset("Authorization:", requestHeader) into theLine
if (theLine > 0) then
-- check the authorization
put word 1 of requestHeader into method
put line theLine of requestHeader into authLine
replace "Authorization: Digest" with empty in authLine
set the itemDelimiter to comma
repeat for each item theItem in authLine
set the itemDelimiter to "="
put item 1 of theItem into theName
repeat until (char 1 of theName <> " ")
delete char 1 of theName
end repeat
replace (theName&"=") with (theName&"◊") in theItem
set the itemDelimiter to "◊"
put item 2 of theItem into theValue
replace quote with empty in theValue
set the itemDelimiter to comma
switch(theName)
case "userName"
put theValue into userName
exit switch
case "realm"
put theValue into realm
exit switch
case "nonce"
put theValue into nonce
exit switch
case "uri"
put theValue into theURL
exit switch
case "qop"
put theValue into qop
exit switch
case "nc"
put theValue into nc
exit switch
case "cnonce"
put theValue into cnonce
exit switch
case "response"
put theValue into digestValue
exit switch
case "opaque"
put theValue into opaque
exit switch
end switch
end repeat
else
put authenticateHeader(realm,"auth",empty,"default") into replyHeader
return FALSE
end if
## edit this to lookup the correct password
put empty into userID
put lookupPassword(userName, userID) into password
if (password is empty) then
put authenticateHeader(realm,"auth",empty,"default") into replyHeader
return FALSE
end if
put makeDigest(userName,password,realm,method,theURL,nonce,nc,cnonce,qop)
into actualValue
put char 1 to length(actualValue) of digestValue into digestValue
if ((digestValue = actualValue) AND (opaque = server_opaque)) then
put
authenticateInfoHeader(userName,password,realm,method,theURL,server_nonce[user
Name]) into replyHeader
put userID into loggedInIDs[theSocket]
put userName into loggedInNames[theSocket]
put base64Encode(userName&tab&thePassword) into loginValue
SetCookie theSocket,"webcf_entry",loginValue
return TRUE
else
-- failed
put authenticateHeader(realm,"auth",empty) into replyHeader
return FALSE
end if
end checkPassword
function authenticateInfoHeader userName,_password,realm,method,theURL,nonce
put makeDigest(userName,_password,realm,empty,theURL,nonce) into response
return "Authentication-Info: next-nonce=""e&nonce"e&comma&"qop="&
quote&auth"e&comma&"rspauth=""e&response"e
end authenticateInfoHeader
function authenticateHeader theRealm,authMethods,isStale,userName,forceNonce
global server_opaque,server_nonce,cfLF
if (userName is empty) then put "default" into userName
if (server_opaque is empty) then put base64Encode(random(4*(the ticks))&
md5Digest(the ticks)) into server_opaque
if (server_nonce is empty) OR (forceNonce) then
put base64Encode("Dummy") into server_nonce
end if
if (isStale is empty) then return "HTTP/1.1 401 Unauthorized"&crLF&
"WWW-Authenticate: Digest"&&"realm=""e&theRealm"e&comma&"qop=""e&
authMethods"e&comma&"nonce=""e&server_nonce"e&comma&"opaque="&
quote&server_opaque"e&comma&"algorithm=""e&"MD5""e&crLF
else
return "HTTP/1.1 401 Unauthorized"&crLF&"Connection: close"&crLF&
"WWW-Authenticate: Digest"&&"realm=""e&theRealm"e&comma&"qop=""e&
authMethods"e&comma&"nonce=""e&server_nonce"e&comma&"opaque="&
quote&server_opaque"e&comma&"stale="&isStale&",algorithm=""e&"MD5"&
quote&crLF
end if
end authenticateHeader
function makeDigest
userName,_password,realm,method,theURL,nonce,nc,cnonce,qop
put md5Digest(userName&colon&realm&colon&_password) into A1
get binaryDecode("H*",A1,A1)
put md5Digest(method&colon&theURL) into A2
get binaryDecode("H*",A2,A2)
if (qop is empty) then
put md5Digest(A1&colon&nonce&colon&A2) into actualValue
else
put md5Digest(A1&colon&nonce&colon&nc&colon&cnonce&colon&qop&colon&A2)
into actualValue
end if
get binaryDecode("H*",actualValue,actualValue)
return actualvalue
end makeDigest
>
> I'm sure it'll be a piece of cake, Rob. :) But please let us know
> what you come up with. The truth is I just want someone else to
> interpret section 3.2.2 of the rfc on digest authorization. I'm
> trying to preserve what few brain cells I have remaining.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.runrev.com/pipermail/use-livecode/attachments/20021120/4e4a9ab0/attachment.html>
More information about the use-livecode
mailing list