/// <summary>
        /// Validates the token signature against the two keys.
        /// </summary>
        /// <param name="token">The token to be validated.</param>
        /// <param name="primaryKey">
        /// The first key to be used for validation.
        /// </param>
        /// <param name="secondaryKey">
        /// The second key to be used for validation if the second key fails.
        /// </param>
        /// <returns></returns>
        private bool ValidateTokenSignature(SimpleWebToken token, byte[] primaryKey, byte[] secondaryKey)
        {
            try
            {
                // try primary key first.
                bool isSignatureValid = token.VerifySignature(primaryKey);

                if (!isSignatureValid)
                {
                    // now try secondary key.
                    isSignatureValid = token.VerifySignature(secondaryKey);

                    if (!isSignatureValid)
                    {
                        return(false);
                    }
                }

                return(true);
            }
            catch (SecurityException)
            {
                return(false);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Factory method for creating a new SimpleWebToken.
        /// </summary>
        /// <param name="issuer">The token issuer.</param>
        /// <param name="audience">The token audience.</param>
        /// <param name="expiresOn">The UTC time when the token should expire.</param>
        /// <param name="claims">The claims to be encoded into the token.</param>
        /// <returns>
        /// A new SimpleWebToken instance with specified values.
        /// </returns>
        public static SimpleWebToken Create(string issuer, string audience, DateTime expiresOn, IEnumerable <Claim> claims)
        {
            if (string.IsNullOrEmpty(issuer))
            {
                throw new ArgumentNullException("issuer");
            }

            var token = new SimpleWebToken();

            token.tokenAudience   = audience;
            token.tokenExpiryTime = expiresOn;
            token.tokenIssuer     = issuer;
            token.tokenClaims     = new List <Claim>();

            if (claims != null)
            {
                foreach (Claim claim in claims)
                {
                    if (IsReservedClaimType(claim.Type))
                    {
                        throw new ArgumentException("ClaimType " + claim.Type + " is reserved for system use");
                    }

                    token.tokenClaims.Add(claim);
                }
            }

            return(token);
        }
        public bool Validate(string swtToken)
        {
            // Validate the token (note that the signature is verified only further down).
            SimpleWebToken token;

            try
            {
                token = SimpleWebToken.Parse(swtToken);
            }
            catch (SecurityException)
            {
                return(false);
            }
            catch (Exception exception)
            {
                if (exception.IsFatal())
                {
                    throw;
                }

                return(false);
            }

            // The token was parsed successfully.

            // Validate issuer.
            TokenIssuer tokenIssuer;

            if ((!Enum.TryParse(token.Issuer, true, out tokenIssuer)) || (!Enum.IsDefined(typeof(TokenIssuer), token.Issuer)))
            {
                return(false);
            }

            // Validate audience
            TokenAudience tokenAudience;

            if ((!Enum.TryParse(token.Audience, true, out tokenAudience)) || (!Enum.IsDefined(typeof(TokenAudience), token.Audience)))
            {
                return(false);
            }

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

            if (!isSignatureValid)
            {
                return(false);
            }

            // Make sure the token is not expired.
            if (token.IsExpiredNow)
            {
                // Token expired.
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Checks whether the token signature is valid using the specified token issuer's keys.
        /// </summary>
        /// <param name="token">the token whose signature should be validated.</param>
        /// <param name="tokenIssuer">The token issuer who keys are to be used for validation.</param>
        /// <returns>
        /// True if the signature could be validated with the specified issuer's keys.
        /// </returns>
        private bool IsSignatureValidForIssuer(SimpleWebToken token, TokenIssuer tokenIssuer)
        {
            if (!this.tokenSigningKeysForIssuer.ContainsKey(tokenIssuer))
            {
                return(false);
            }

            var keys = this.tokenSigningKeysForIssuer[tokenIssuer];

            return(this.ValidateTokenSignature(token, keys.Item1, keys.Item2));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Creates a SimpleWebToken by parsing the form-encoded
        /// string representation of the token.
        /// </summary>
        /// <param name="encodedToken">The encoded token string.</param>
        /// <returns>
        /// An instance of SimpleWebToken.
        /// </returns>
        /// <exception cref="SecurityException">
        /// Thrown if errors are encountered while processing the token string.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown if the issuer secret or encoded token is null or invalid.
        /// </exception>
        public static SimpleWebToken Parse(string encodedToken)
        {
            if (string.IsNullOrWhiteSpace(encodedToken))
            {
                throw new SecurityException("The encoded token is not valid.");
            }

            var token = new SimpleWebToken();

            token.Decode(encodedToken);
            return(token);
        }
        /// <summary>
        /// Factory method for creating SWT tokens. Use this overload when there is a requirement
        /// to encode additional claims into the token.
        /// </summary>
        /// <param name="issuer">The entity issuing the token.</param>
        /// <param name="audience">The entity receiving the token.</param>
        /// <param name="expiresOnUtc">The expiry time for the token in UTC.</param>
        /// <param name="additionalClaims">
        /// Any additional claims to be included as part of the token.
        /// </param>
        /// <param name="signingKey">The token signing key.</param>
        /// <returns>
        /// An instance of SimpleWebToken class.
        /// </returns>
        public static SimpleWebToken CreateToken(
            TokenIssuer issuer,
            TokenAudience audience,
            DateTime expiresOnUtc,
            IEnumerable <Claim> additionalClaims,
            byte[] signingKey)
        {
            if (issuer == TokenIssuer.Unknown)
            {
                throw new ArgumentException(
                          "{0} is not not allowed as token issuer.".FormatInvariant(issuer.ToString()));
            }

            if (audience == TokenAudience.Unknown)
            {
                throw new ArgumentException(
                          "{0} is not allowed as token audience.".FormatInvariant(audience.ToString()));
            }

            if (signingKey == null || signingKey.Length == 0)
            {
                throw new ArgumentException("The signing key is not valid.");
            }

            var claims = new List <Claim>();

            if (additionalClaims != null)
            {
                claims.AddRange(additionalClaims);
            }

            var token = SimpleWebToken.Create(issuer.ToString(), audience.ToString(), expiresOnUtc, claims);

            token.SignToken(signingKey);
            return(token);
        }
        /// <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));
        }