/// <summary>
 /// Logs the authentication result.
 /// </summary>
 /// <param name="authenticationResult">
 /// The authentication result to be logged.
 /// </param>
 private void LogAuthenticationResult(AuthenticationResult authenticationResult)
 {
 }
        /// <summary>
        /// Authenticates the request using Bearer scheme.
        /// </summary>
        /// <param name="request">The request to be authenticated.</param>
        /// <returns>
        /// An instance of AuthenticationResult which specifies if the authentication was successful or not.
        /// If successful, it will contain the IPrincipal.
        /// If not successful, it will contain the error message.
        /// </returns>
        public override AuthenticationResult Authenticate(HttpRequestMessage request)
        {
            // Validate the request first.
            AuthenticationResult authenticationResult;

            if (!this.ValidateRequest(request, out authenticationResult))
            {
                return(authenticationResult);
            }

            // Validate the token (note that the signature is verified only further down).
            SimpleWebToken token;

            try
            {
                string tokenString = request.Headers.Authorization.Parameter;
                token = SimpleWebToken.Parse(tokenString);
            }
            catch (FormatException)
            {
                return
                    (AuthenticationResult.CreateFailedAuthenticationResult(
                         "The bearer token is not in a valid format."));
            }
            catch (SecurityException exception)
            {
                return(AuthenticationResult.CreateFailedAuthenticationResult(exception.Message));
            }
            catch (Exception exception)
            {
                if (exception.IsFatal())
                {
                    throw;
                }

                return
                    (AuthenticationResult.CreateFailedAuthenticationResult(
                         "An unexpected error occurred while parsing the token."));
            }

            // Validate issuer.
            TokenIssuer tokenIssuer;

            if ((!Enum.TryParse(token.Issuer, true, out tokenIssuer)) || (!Enum.IsDefined(typeof(TokenIssuer), token.Issuer)))
            {
                return(AuthenticationResult.CreateFailedAuthenticationResult(
                           "Unrecognized token issuer: '{0}'",
                           token.Issuer));
            }

            // Validate audience
            TokenAudience tokenAudience;

            if ((!Enum.TryParse(token.Audience, true, out tokenAudience)) || (!Enum.IsDefined(typeof(TokenAudience), token.Audience)))
            {
                return(AuthenticationResult.CreateFailedAuthenticationResult(
                           "Unrecognized token audience: '{0}'",
                           token.Audience));
            }

            // Now validate the signature using the specified issuer's keys
            bool isSignatureValid = this.IsSignatureValidForIssuer(token, tokenIssuer);

            if (!isSignatureValid)
            {
                return(AuthenticationResult.CreateFailedAuthenticationResult("The token signature is not valid."));
            }

            // Make sure the token is not expired.
            if (token.IsExpiredNow)
            {
                // Token expired.
                return(AuthenticationResult.CreateFailedAuthenticationResult(
                           "The token expired at {0}",
                           token.ExpiresOn.ToRoundtripFormatString()));
            }

            // Identify the roles for this principal.
            IEnumerable <Claim> roleClaims = GetRoleClaims(tokenIssuer, tokenAudience);

            if (roleClaims == null)
            {
                return(AuthenticationResult.CreateFailedAuthenticationResult(
                           "This combination of token issuer and audience is not allowed for this service."));
            }

            var claims = new List <Claim>();

            // We wont allow the caller to specify roles, we will assign the roles here.
            claims.AddRange(token.Claims.Where(c => c.Type != HolMonClaimTypes.Role));

            // Adding claims as we see fit.
            claims.AddRange(roleClaims);

            claims.Add(new Claim(HolMonClaimTypes.AuthenticationScheme, this.AuthenticationScheme));
            claims.Add(new Claim(HolMonClaimTypes.TokenAudience, token.Audience));
            claims.Add(new Claim(HolMonClaimTypes.TokenIssuer, token.Issuer));

            this.LogClaims(claims);

            var identity  = new ClaimsIdentity(claims, request.Headers.Authorization.Scheme);
            var principal = new ClaimsPrincipal(identity);

            return(AuthenticationResult.CreateSuccessfulAuthenticationResult(principal));
        }