/// <summary>
        /// Executes the <see cref="DigestAccessAuthenticationMiddleware"/>.
        /// </summary>
        /// <param name="context">The context of the current request.</param>
        /// <returns>A task that represents the execution of this middleware.</returns>
        public override async Task Invoke(HttpContext context)
        {
            if (!AuthenticationUtility.TryAuthenticate(context, Options.RequireSecureConnection, AuthorizationHeaderParser, TryAuthenticate))
            {
                context.Response.StatusCode = AuthenticationUtility.HttpNotAuthorizedStatusCode;
                string etag = context.Response.Headers[HeaderNames.ETag];
                if (string.IsNullOrEmpty(etag))
                {
                    etag = "no-entity-tag";
                }
                Func <string> opaqueGenerator = Options.OpaqueGenerator;
                Func <byte[]> nonceSecret     = Options.NonceSecret;
                Func <DateTime, string, byte[], string> nonceGenerator = Options.NonceGenerator;
                string staleNonce = context.Items["staleNonce"] as string ?? "FALSE";
                context.Response.Headers.Add(HeaderNames.WWWAuthenticate, "{0} realm=\"{1}\", qop=\"{2}\", nonce=\"{3}\", opaque=\"{4}\", stale=\"{5}\", algorithm=\"{6}\"".FormatWith(
                                                 AuthenticationScheme,
                                                 Options.Realm,
                                                 DigestAuthenticationUtility.CredentialQualityOfProtectionOptions,
                                                 nonceGenerator(DateTime.UtcNow, etag, nonceSecret()),
                                                 opaqueGenerator(),
                                                 staleNonce,
                                                 DigestAuthenticationUtility.ParseAlgorithm(Options.Algorithm)));
                await context.WriteHttpNotAuthorizedBody(Options.HttpNotAuthorizedBody).ContinueWithSuppressedContext();

                return;
            }
            await Next.Invoke(context).ContinueWithSuppressedContext();
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="DigestAccessAuthenticationOptions"/> class.
 /// </summary>
 public DigestAccessAuthenticationOptions()
 {
     Algorithm          = HashAlgorithmType.MD5;
     OpaqueGenerator    = DigestAuthenticationUtility.DefaultOpaqueGenerator;
     NonceExpiredParser = DigestAuthenticationUtility.DefaultNonceExpiredParser;
     NonceGenerator     = DigestAuthenticationUtility.DefaultNonceGenerator;
     NonceSecret        = () => DigestAuthenticationUtility.DefaultPrivateKey;
     DigestAccessSigner = parameters =>
     {
         string ha1 = DigestAuthenticationUtility.ComputeHash1(parameters.Credentials, parameters.Password, parameters.Algorithm);
         string ha2 = DigestAuthenticationUtility.ComputeHash2(parameters.Credentials, parameters.HttpMethod, parameters.Algorithm);
         return(DigestAuthenticationUtility.ComputeResponse(parameters.Credentials, ha1, ha2, parameters.Algorithm));
     };
 }