예제 #1
0
        /// <summary>
        /// Executes the authentication failure action, sending a WWW-Authenticate header with the configured realm out through the context and
        /// setting the HTTP status code to 401 (Unauthorized).
        /// </summary>
        /// <remarks>	ebrown, 1/3/2011. </remarks>
        /// <exception cref="ArgumentNullException">	Thrown when one or more required arguments are null. </exception>
        /// <param name="context">		    The incoming context. </param>
        /// <param name="inspectorResults">	The set of failed inspector results. </param>
        /// <returns>	Null for an IPrincipal and ShouldTerminateRequest to true since a WWW-Authenticate header is sent. </returns>
        public override FailureHandlerAction OnAuthenticationFailure(HttpContextBase context, Dictionary <IAuthenticator, AuthenticationResult> inspectorResults)
        {
            if (null == context)
            {
                throw new ArgumentNullException("context");
            }

            //http://en.wikipedia.org/wiki/Digest_access_authentication
            //not sure that 'auth-int' is supported across the board, so stick with just 'auth'
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;

            string stale = "FALSE";
            //attempt to extract credentials from header -- assuming they might be stale
            DigestHeader    digestHeader;
            HttpRequestBase request = context.Request;

            if (HttpDigestAuthHeaderParser.TryExtractDigestHeader(request.HttpMethod ?? request.RequestType, request.RetrieveHeader(HttpHeaderFields.Authorization), out digestHeader) &&
                NonceManager.Validate(digestHeader.Nonce, request.UserHostAddress, privateHashEncoder) &&
                NonceManager.IsStale(digestHeader.Nonce, Configuration.NonceValidDuration))
            {
                stale = "TRUE";
            }

            context.Response.AddHeader("WWW-Authenticate", String.Format(CultureInfo.InvariantCulture,
                                                                         "Digest realm=\"{0}\", nonce=\"{1}\", opaque=\"{2}\", stale={3}, algorithm=MD5, qop=\"{4}\"",
                                                                         Configuration.Realm, NonceManager.Generate(request.UserHostAddress, privateHashEncoder), Opaque.Current(),
                                                                         stale, DigestQualityOfProtectionType.Authentication.ToEnumValueString()));

            return(new FailureHandlerAction()
            {
                User = null, ShouldTerminateRequest = true
            });
        }
예제 #2
0
        /// <summary>   Authenticates a HttpContextBase given a specified MembershipProvider. </summary>
        /// <remarks>   ebrown, 1/3/2011. </remarks>
        /// <exception cref="ArgumentNullException">    Thrown when one or more required arguments are null. </exception>
        /// <exception cref="Exception">                Thrown when an unexpected exception occurs. </exception>
        /// <param name="context">  The context. </param>
        /// <returns>   A success or failure if the MembershipProvider validated the credentials found in the header. </returns>
        public override AuthenticationResult Authenticate(HttpContextBase context)
        {
            try
            {
                if (null == context)
                {
                    throw new ArgumentNullException("context");
                }

                HttpRequestBase request    = context.Request;
                string          authHeader = request.Headers["Authorization"];

                Log.InfoFormat(CultureInfo.InvariantCulture, "Authorization header [{0}] received", authHeader.IfMissing("**Missing**"));

                ////attempt to extract credentials from header
                DigestHeader digestHeader;
                if (!HttpDigestAuthHeaderParser.TryExtractDigestHeader(request.HttpMethod ?? request.RequestType, authHeader, out digestHeader))
                {
                    //don't log an event since there was nothing to succeed / fail
                    return(new AuthenticationResult(false, null, "No digest credentials found in HTTP header"));
                }

                MembershipProvider membershipProvider = null;
                MembershipUser     membershipUser     = null;
                string             userPassword       = null;

                //try our specially configured function first, and fail out to membership if not available
                if (null != Configuration.PasswordRetriever)
                {
                    userPassword = Configuration.PasswordRetriever.GetPassword(digestHeader.UserName);
                }
                else
                {
                    membershipProvider = MembershipProviderLocator.GetProvider(Configuration.ProviderName);
                    if (null == membershipProvider)
                    {
                        throw new ArgumentException("MembershipProvider specified in configuration cannot be found, but is required to lookup user password for comparison");
                    }

                    membershipUser = membershipProvider.GetUser(digestHeader.UserName, true);
                    userPassword   = membershipUser.GetPassword();
                }

                //three things validate this digest request -- that the nonce matches the given address, that its not stale
                //and that the credentials match the given realm / opaque / password
                if (NonceManager.Validate(digestHeader.Nonce, request.UserHostAddress, privateHashEncoder) &&
                    !NonceManager.IsStale(digestHeader.Nonce, Configuration.NonceValidDuration) &&
                    digestHeader.MatchesCredentials(Configuration.Realm, Opaque.Current(), userPassword))
                {
                    if (null != membershipProvider)
                    {
                        new AuthenticationSuccessEvent(this, digestHeader.UserName).Raise();
                    }

                    IPrincipal principal = GetPrincipal(context, membershipUser, new NetworkCredential(digestHeader.UserName, userPassword));
                    IIdentity  identity  = null != principal ? principal.Identity : null;
                    if (null != identity && identity.IsAuthenticated)
                    {
                        new AuthenticationSuccessEvent(this, identity.Name).Raise();
                        return(new AuthenticationResult(true, principal, string.Empty));
                    }
                }

                new AuthenticationFailureEvent(this, digestHeader.UserName).Raise();
                return(new AuthenticationResult(false, null, string.Empty));
            }
            catch (Exception)
            {
                new AuthenticationFailureEvent(this, string.Empty).Raise();
                throw;
            }
        }