/// <summary> /// Create a WWW-Authenticate header /// </summary> public void CreateChallenge(IRequest request, IResponse response) { var nonce = _nonceService.CreateNonce(); var challenge = new StringBuilder(); challenge.AppendFormat(@"Digest realm=""{0}"", ", _realmRepository.GetRealm(request)); challenge.AppendFormat(@"nonce=""{0}"", ", nonce); challenge.Append(@"qop=""auth"", "); challenge.Append("algorithm=MD5"); /* RFC 2617 3.3 * Because the client is required to return the value of the opaque * directive given to it by the server for the duration of a session, * the opaque data may be used to transport authentication session state * information. (Note that any such use can also be accomplished more * easily and safely by including the state in the nonce.) For example, * a server could be responsible for authenticating content that * actually sits on another server. It would achieve this by having the * first 401 response include a domain directive whose value includes a * URI on the second server, and an opaque directive whose value * contains the state information. The client will retry the request, at * which time the server might respond with a 301/302 redirection, * pointing to the URI on the second server. The client will follow the * redirection, and pass an Authorization header , including the * <opaque> data. */ // , opaque=""" + Guid.NewGuid().ToString().Replace("-", string.Empty) + "\"" /* Disable the stale mechanism * We should really generate the responses directly in these classes. * challenge.Append(", stale="); * challenge.Append((bool)options[0] ? "true" : "false"); * challenge.Append("false"); * */ response.AddHeader("WWW-Authenticate", challenge.ToString()); response.StatusCode = 401; }