Exemple #1
0
        public bool Equals(CsrfToken other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;

            return this.RandomBytes.SequenceEqual(other.RandomBytes)
                && other.CreatedDate.Equals(this.CreatedDate)
                && this.Hmac.SequenceEqual(other.Hmac);
        }
        public void Should_return_token_ok_if_tokens_match_and_no_expiry_set()
        {
            DateTime date = DateTime.Now;
            var tokenOne = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 2, 3 } };
            var tokenTwo = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 2, 3 } };
            tokenOne.CreateHmac(this.hmacProvider);
            tokenTwo.CreateHmac(this.hmacProvider);

            var result = this.validator.Validate(tokenOne, tokenTwo);

            result.ShouldEqual(CsrfTokenValidationResult.Ok);
        }
        public void Should_return_token_mismatch_if_tokens_differ()
        {
            DateTime date = DateTime.Now;
            var tokenOne = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 2, 3 } };
            var tokenTwo = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 4, 3 } };
            tokenOne.CreateHmac(this.hmacProvider);
            tokenTwo.CreateHmac(this.hmacProvider);

            var result = this.validator.Validate(tokenOne, tokenTwo);

            result.ShouldEqual(CsrfTokenValidationResult.TokenMismatch);
        }
        public void Should_return_token_mismatch_if_random_bytes_empty()
        {
            DateTime date = DateTime.Now;
            var tokenOne = new CsrfToken { CreatedDate = date, RandomBytes = ArrayCache.Empty<byte>() };
            var tokenTwo = new CsrfToken { CreatedDate = date, RandomBytes = ArrayCache.Empty<byte>() };
            tokenOne.CreateHmac(this.hmacProvider);
            tokenTwo.CreateHmac(this.hmacProvider);

            var result = this.validator.Validate(tokenOne, tokenTwo);

            result.ShouldEqual(CsrfTokenValidationResult.TokenTamperedWith);
        }
Exemple #5
0
        private static CsrfToken GetCookieToken(Request request)
        {
            CsrfToken cookieToken = null;

            string cookieTokenString;

            if (request.Cookies.TryGetValue(CsrfToken.DEFAULT_CSRF_KEY, out cookieTokenString))
            {
                cookieToken = (CsrfToken)CsrfStartup.ObjectSerializer.Deserialize(HttpUtility.UrlDecode(cookieTokenString));
            }

            return(cookieToken);
        }
Exemple #6
0
        private static CsrfToken GetCookieToken(Request request)
        {
            CsrfToken cookieToken = null;

            string cookieTokenString;

            if (request.Cookies.TryGetValue(CsrfToken.DEFAULT_CSRF_KEY, out cookieTokenString))
            {
                cookieToken = ParseToCsrfToken(cookieTokenString);
            }

            return(cookieToken);
        }
Exemple #7
0
        private static CsrfToken GetFormToken(Request request)
        {
            CsrfToken formToken = null;

            var formTokenString = request.Form[CsrfToken.DEFAULT_CSRF_KEY].Value;

            if (formTokenString != null)
            {
                formToken = (CsrfToken)CsrfStartup.ObjectSerializer.Deserialize(formTokenString);
            }

            return(formToken);
        }
Exemple #8
0
        private static CsrfToken GetProvidedToken(Request request)
        {
            CsrfToken providedToken = null;

            var providedTokenString = request.Form[CsrfToken.DEFAULT_CSRF_KEY].Value ?? request.Headers[CsrfToken.DEFAULT_CSRF_KEY].FirstOrDefault();

            if (providedTokenString != null)
            {
                providedToken = ParseToCsrfToken(providedTokenString);
            }

            return(providedToken);
        }
Exemple #9
0
        /// <summary>
        /// Creates a new csrf token for this response with an optional salt.
        /// Only necessary if a particular route requires a new token for each request.
        /// </summary>
        /// <param name="module">Nancy module</param>
        /// <returns></returns>
        public static void CreateNewCsrfToken(this INancyModule module)
        {
            var token = new CsrfToken
            {
                CreatedDate = DateTime.Now,
            };
            token.CreateRandomBytes();
            token.CreateHmac(CsrfApplicationStartup.CryptographyConfiguration.HmacProvider);

            var tokenString = CsrfApplicationStartup.ObjectSerializer.Serialize(token);

            module.Context.Items[CsrfToken.DEFAULT_CSRF_KEY] = tokenString;
        }
Exemple #10
0
        private static CsrfToken GetCookieToken(Request request)
        {
            CsrfToken cookieToken = null;

            string cookieTokenString;

            if (request.Cookies.TryGetValue(CsrfToken.DEFAULT_CSRF_KEY, out cookieTokenString))
            {
                cookieToken = CsrfApplicationStartup.ObjectSerializer.Deserialize(cookieTokenString) as CsrfToken;
            }

            return(cookieToken);
        }
Exemple #11
0
        private static CsrfToken GetProvidedToken(Request request)
        {
            CsrfToken providedToken = null;

            var providedTokenString = request.Form[CsrfToken.DEFAULT_CSRF_KEY].Value ?? request.Headers[CsrfToken.DEFAULT_CSRF_KEY].FirstOrDefault();

            if (providedTokenString != null)
            {
                providedToken = CsrfApplicationStartup.ObjectSerializer.Deserialize(providedTokenString) as CsrfToken;
            }

            return(providedToken);
        }
        public void Should_return_token_tampered_with_if_hmac_incorrect()
        {
            DateTime date = DateTime.Now;
            var tokenOne = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 2, 3 } };
            var tokenTwo = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 2, 3 } };
            tokenOne.CreateHmac(this.hmacProvider);
            tokenTwo.CreateHmac(this.hmacProvider);
            tokenOne.Hmac[0] -= 1;
            tokenTwo.Hmac[0] -= 1;

            var result = this.validator.Validate(tokenOne, tokenTwo);

            result.ShouldEqual(CsrfTokenValidationResult.TokenTamperedWith);
        }
Exemple #13
0
        /// <summary>
        /// Creates a new csrf token for this response with an optional salt.
        /// Only necessary if a particular route requires a new token for each request.
        /// </summary>
        /// <param name="module">Nancy module</param>
        /// <returns></returns>
        public static void CreateNewCsrfToken(this NancyModule module)
        {
            var token = new CsrfToken
            {
                CreatedDate = DateTime.Now,
            };

            token.CreateRandomBytes();
            token.CreateHmac(CsrfApplicationStartup.CryptographyConfiguration.HmacProvider);

            var tokenString = CsrfApplicationStartup.ObjectSerializer.Serialize(token);

            module.Context.Items[CsrfToken.DEFAULT_CSRF_KEY] = tokenString;
        }
        /// <summary>
        /// Creates a new csrf token with an optional salt.
        /// Does not store the token in context.
        /// </summary>
        /// <returns>The generated token</returns>
        internal static string GenerateTokenString(CryptographyConfiguration cryptographyConfiguration = null)
        {
            cryptographyConfiguration = cryptographyConfiguration ?? CsrfApplicationStartup.CryptographyConfiguration;
            var token = new CsrfToken
            {
                CreatedDate = DateTime.Now,
            };

            token.CreateRandomBytes();
            token.CreateHmac(cryptographyConfiguration.HmacProvider);
            var tokenString = CsrfApplicationStartup.ObjectSerializer.Serialize(token);

            return(tokenString);
        }
Exemple #15
0
        public bool Equals(CsrfToken other)
        {
            if (ReferenceEquals(null, other))
            {
                return(false);
            }
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            return(this.RandomBytes.SequenceEqual(other.RandomBytes) &&
                   other.CreatedDate.Equals(this.CreatedDate) &&
                   this.Hmac.SequenceEqual(other.Hmac));
        }
        /// <summary>
        /// Enables Csrf token generation.
        /// This is disabled by default.
        /// </summary>
        /// <param name="pipelines">Application pipelines</param>
        public static void Enable(IPipelines pipelines, CryptographyConfiguration cryptographyConfiguration = null)
        {
            cryptographyConfiguration = cryptographyConfiguration ?? CsrfApplicationStartup.CryptographyConfiguration;

            var postHook = new PipelineItem <Action <NancyContext> >(
                CsrfHookName,
                context =>
            {
                if (context.Response == null || context.Response.Cookies == null || context.Request.Method.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase))
                {
                    return;
                }

                if (context.Items.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                {
                    context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY,
                                                                 (string)context.Items[CsrfToken.DEFAULT_CSRF_KEY],
                                                                 true));
                    return;
                }

                if (context.Request.Cookies.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                {
                    var decodedValue = HttpUtility.UrlDecode(context.Request.Cookies[CsrfToken.DEFAULT_CSRF_KEY]);
                    var cookieToken  = CsrfApplicationStartup.ObjectSerializer.Deserialize(decodedValue) as CsrfToken;

                    if (CsrfApplicationStartup.TokenValidator.CookieTokenStillValid(cookieToken))
                    {
                        context.Items[CsrfToken.DEFAULT_CSRF_KEY] = decodedValue;
                        return;
                    }
                }

                var token = new CsrfToken
                {
                    CreatedDate = DateTime.Now,
                };
                token.CreateRandomBytes();
                token.CreateHmac(cryptographyConfiguration.HmacProvider);
                var tokenString = CsrfApplicationStartup.ObjectSerializer.Serialize(token);

                context.Items[CsrfToken.DEFAULT_CSRF_KEY] = tokenString;
                context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY, tokenString, true));
            });

            pipelines.AfterRequest.AddItemToEndOfPipeline(postHook);
        }
Exemple #17
0
        /// <summary>
        /// Enables Csrf token generation.
        /// This is disabled by default.
        /// </summary>
        /// <param name="pipelines">Application pipelines</param>
        public static void Enable(IPipelines pipelines, CryptographyConfiguration cryptographyConfiguration = null)
        {
            cryptographyConfiguration = cryptographyConfiguration ?? CsrfApplicationStartup.CryptographyConfiguration;

            var postHook = new PipelineItem<Action<NancyContext>>(
                CsrfHookName,
                context =>
                {
                    if (context.Response == null || context.Response.Cookies == null || context.Request.Method.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase))
                    {
                        return;
                    }

                    if (context.Items.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                    {
                        context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY,
                                                                     (string)context.Items[CsrfToken.DEFAULT_CSRF_KEY],
                                                                     true));
                        return;
                    }

                    if (context.Request.Cookies.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                    {
                        var decodedValue = HttpUtility.UrlDecode(context.Request.Cookies[CsrfToken.DEFAULT_CSRF_KEY]);
                        var cookieToken = CsrfApplicationStartup.ObjectSerializer.Deserialize(decodedValue) as CsrfToken;

                        if (CsrfApplicationStartup.TokenValidator.CookieTokenStillValid(cookieToken))
                        {
                            context.Items[CsrfToken.DEFAULT_CSRF_KEY] = decodedValue;
                            return;
                        }
                    }

                    var token = new CsrfToken
                    {
                        CreatedDate = DateTime.Now,
                    };
                    token.CreateRandomBytes();
                    token.CreateHmac(cryptographyConfiguration.HmacProvider);
                    var tokenString = CsrfApplicationStartup.ObjectSerializer.Serialize(token);

                    context.Items[CsrfToken.DEFAULT_CSRF_KEY] = tokenString;
                    context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY, tokenString, true));
                });

            pipelines.AfterRequest.AddItemToEndOfPipeline(postHook);
        }
        /// <summary>
        /// Validates a pair of tokens
        /// </summary>
        /// <param name="tokenOne">First token (usually from either a form post or querystring)</param>
        /// <param name="tokenTwo">Second token (usually from a cookie)</param>
        /// <param name="validityPeriod">Optional period that the tokens are valid for</param>
        /// <returns>Token validation result</returns>
        public CsrfTokenValidationResult Validate(CsrfToken tokenOne, CsrfToken tokenTwo, TimeSpan?validityPeriod = new TimeSpan?())
        {
            if (tokenOne == null || tokenTwo == null)
            {
                return(CsrfTokenValidationResult.TokenMissing);
            }

            if (!tokenOne.Equals(tokenTwo))
            {
                return(CsrfTokenValidationResult.TokenMismatch);
            }

            if (tokenOne.RandomBytes == null || tokenOne.RandomBytes.Length == 0)
            {
                return(CsrfTokenValidationResult.TokenTamperedWith);
            }

            var newToken = new CsrfToken
            {
                CreatedDate = tokenOne.CreatedDate,
                RandomBytes = tokenOne.RandomBytes,
            };

            newToken.CreateHmac(this.hmacProvider);
            if (!newToken.Hmac.SequenceEqual(tokenOne.Hmac))
            {
                return(CsrfTokenValidationResult.TokenTamperedWith);
            }

            if (validityPeriod.HasValue)
            {
                var expiryDate = tokenOne.CreatedDate.Add(validityPeriod.Value);

                if (DateTime.Now > expiryDate)
                {
                    return(CsrfTokenValidationResult.TokenExpired);
                }
            }

            return(CsrfTokenValidationResult.Ok);
        }
        /// <summary>
        /// Validates that a cookie token is still valid with the current configuration / keys
        /// </summary>
        /// <param name="cookieToken">Token to validate</param>
        /// <returns>True if valid, false otherwise</returns>
        public bool CookieTokenStillValid(CsrfToken cookieToken)
        {
            if (cookieToken == null || cookieToken.RandomBytes == null || cookieToken.RandomBytes.Length == 0)
            {
                return false;
            }

            var newToken = new CsrfToken
            {
                CreatedDate = cookieToken.CreatedDate,
                RandomBytes = cookieToken.RandomBytes,
            };
            newToken.CreateHmac(this.hmacProvider);

            if (!newToken.Hmac.SequenceEqual(cookieToken.Hmac))
            {
                return false;
            }

            return true;
        }
Exemple #20
0
        /// <summary>
        /// Creates a new csrf token with an optional salt.
        /// Does not store the token in context.
        /// </summary>
        /// <returns>The generated token</returns>
        internal static string GenerateTokenString(CryptographyConfiguration cryptographyConfiguration = null)
        {
            cryptographyConfiguration = cryptographyConfiguration ?? CsrfApplicationStartup.CryptographyConfiguration;
            var token = new CsrfToken
            {
                CreatedDate = DateTimeOffset.Now
            };

            token.CreateRandomBytes();
            token.CreateHmac(cryptographyConfiguration.HmacProvider);

            var builder = new StringBuilder();

            builder.AppendFormat("RandomBytes{0}{1}", ValueDelimiter, Convert.ToBase64String(token.RandomBytes));
            builder.Append(PairDelimiter);
            builder.AppendFormat("Hmac{0}{1}", ValueDelimiter, Convert.ToBase64String(token.Hmac));
            builder.Append(PairDelimiter);
            builder.AppendFormat("CreatedDate{0}{1}", ValueDelimiter, token.CreatedDate.ToString("o", CultureInfo.InvariantCulture));

            return(builder.ToString());
        }
Exemple #21
0
        /// <summary>
        /// Enables Csrf token generation.
        /// This is enabled automatically so there should be no reason to call this manually.
        /// </summary>
        /// <param name="pipelines">Application pipelines</param>
        public static void Enable(IPipelines pipelines)
        {
            var postHook = new PipelineItem <Action <NancyContext> >(
                CsrfHookName,
                context =>
            {
                if (context.Response == null || context.Response.Cookies == null)
                {
                    return;
                }

                if (context.Items.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                {
                    context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY,
                                                                 (string)context.Items[CsrfToken.DEFAULT_CSRF_KEY],
                                                                 true));
                    return;
                }

                if (context.Request.Cookies.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                {
                    context.Items[CsrfToken.DEFAULT_CSRF_KEY] =
                        HttpUtility.UrlDecode(context.Request.Cookies[CsrfToken.DEFAULT_CSRF_KEY]);
                    return;
                }

                var token = new CsrfToken
                {
                    CreatedDate = DateTime.Now,
                };
                token.CreateRandomBytes();
                token.CreateHmac(CsrfStartup.CryptographyConfiguration.HmacProvider);
                var tokenString = CsrfStartup.ObjectSerializer.Serialize(token);

                context.Items[CsrfToken.DEFAULT_CSRF_KEY] = tokenString;
                context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY, tokenString, true));
            });

            pipelines.AfterRequest.AddItemToEndOfPipeline(postHook);
        }
        /// <summary>
        /// Validates a pair of tokens
        /// </summary>
        /// <param name="tokenOne">First token (usually from either a form post or querystring)</param>
        /// <param name="tokenTwo">Second token (usually from a cookie)</param>
        /// <param name="validityPeriod">Optional period that the tokens are valid for</param>
        /// <returns>Token validation result</returns>
        public CsrfTokenValidationResult Validate(CsrfToken tokenOne, CsrfToken tokenTwo, TimeSpan? validityPeriod = new TimeSpan?())
        {
            if (tokenOne == null || tokenTwo == null)
            {
                return CsrfTokenValidationResult.TokenMissing;
            }

            if (!tokenOne.Equals(tokenTwo))
            {
                return CsrfTokenValidationResult.TokenMismatch;
            }

            if (tokenOne.RandomBytes == null || tokenOne.RandomBytes.Length == 0)
            {
                return CsrfTokenValidationResult.TokenTamperedWith;
            }

            var newToken = new CsrfToken
                               {
                                   CreatedDate = tokenOne.CreatedDate,
                                   RandomBytes = tokenOne.RandomBytes,
                               };
            newToken.CreateHmac(this.hmacProvider);
            if (!newToken.Hmac.SequenceEqual(tokenOne.Hmac))
            {
                return CsrfTokenValidationResult.TokenTamperedWith;
            }

            if (validityPeriod.HasValue)
            {
                var expiryDate = tokenOne.CreatedDate.Add(validityPeriod.Value);

                if (DateTime.Now > expiryDate)
                {
                    return CsrfTokenValidationResult.TokenExpired;
                }
            }

            return CsrfTokenValidationResult.Ok;
        }
Exemple #23
0
        /// <summary>
        /// Enables Csrf token generation.
        /// This is enabled automatically so there should be no reason to call this manually.
        /// </summary>
        /// <param name="pipelines">Application pipelines</param>
        public static void Enable(IPipelines pipelines)
        {
            var postHook = new PipelineItem<Action<NancyContext>>(
                CsrfHookName,
                context =>
                {
                    if (context.Response == null || context.Response.Cookies == null)
                    {
                        return;
                    }

                    if (context.Items.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                    {
                        context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY,
                                                                     (string)context.Items[CsrfToken.DEFAULT_CSRF_KEY],
                                                                     true));
                        return;
                    }

                    if (context.Request.Cookies.ContainsKey(CsrfToken.DEFAULT_CSRF_KEY))
                    {
                        context.Items[CsrfToken.DEFAULT_CSRF_KEY] =
                            HttpUtility.UrlDecode(context.Request.Cookies[CsrfToken.DEFAULT_CSRF_KEY]);
                        return;
                    }

                    var token = new CsrfToken
                    {
                        CreatedDate = DateTime.Now,
                    };
                    token.CreateRandomBytes();
                    token.CreateHmac(CsrfStartup.CryptographyConfiguration.HmacProvider);
                    var tokenString = CsrfStartup.ObjectSerializer.Serialize(token);

                    context.Items[CsrfToken.DEFAULT_CSRF_KEY] = tokenString;
                    context.Response.Cookies.Add(new NancyCookie(CsrfToken.DEFAULT_CSRF_KEY, tokenString, true));
                });

            pipelines.AfterRequest.AddItemToEndOfPipeline(postHook);
        }
        /// <summary>
        /// Validates that a cookie token is still valid with the current configuration / keys
        /// </summary>
        /// <param name="cookieToken">Token to validate</param>
        /// <returns>True if valid, false otherwise</returns>
        public bool CookieTokenStillValid(CsrfToken cookieToken)
        {
            if (cookieToken == null || cookieToken.RandomBytes == null || cookieToken.RandomBytes.Length == 0)
            {
                return(false);
            }

            var newToken = new CsrfToken
            {
                CreatedDate = cookieToken.CreatedDate,
                RandomBytes = cookieToken.RandomBytes,
            };

            newToken.CreateHmac(this.hmacProvider);

            if (!newToken.Hmac.SequenceEqual(cookieToken.Hmac))
            {
                return(false);
            }

            return(true);
        }
Exemple #25
0
 /// <summary>
 /// Creates a new csrf token with an optional salt.
 /// Does not store the token in context.
 /// </summary>
 /// <returns>The generated token</returns>
 internal static string GenerateTokenString(CryptographyConfiguration cryptographyConfiguration = null)
 {
     cryptographyConfiguration = cryptographyConfiguration ?? CsrfApplicationStartup.CryptographyConfiguration;
     var token = new CsrfToken
     {
         CreatedDate = DateTime.Now,
     };
     token.CreateRandomBytes();
     token.CreateHmac(cryptographyConfiguration.HmacProvider);
     var tokenString = CsrfApplicationStartup.ObjectSerializer.Serialize(token);
     return tokenString;
 }
        public void Should_return_token_expired_if_it_has()
        {
            DateTime date = DateTime.Now.AddHours(-1);
            var tokenOne = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 2, 3 } };
            var tokenTwo = new CsrfToken { CreatedDate = date, RandomBytes = new byte[] { 1, 2, 3 } };
            tokenOne.CreateHmac(this.hmacProvider);
            tokenTwo.CreateHmac(this.hmacProvider);

            var result = this.validator.Validate(tokenOne, tokenTwo, validityPeriod: new TimeSpan(0, 30, 0));

            result.ShouldEqual(CsrfTokenValidationResult.TokenExpired);
        }
 /// <summary>
 /// Gets a byte array representation of the csrf token for generating
 /// hmacs
 /// </summary>
 /// <param name="token">Token</param>
 /// <returns>Byte array representing the token</returns>
 public static byte[] GetCsrfTokenBytes(this CsrfToken token)
 {
     return(token.RandomBytes
            .Concat(BitConverter.GetBytes(token.CreatedDate.UtcTicks))
            .ToArray());
 }
 /// <summary>
 /// Calculates and sets the Hmac property on a given token
 /// </summary>
 /// <param name="token">Token</param>
 /// <param name="hmacProvider">Hmac provider to use</param>
 /// <returns>Hmac bytes</returns>
 public static void CreateHmac(this CsrfToken token, IHmacProvider hmacProvider)
 {
     token.Hmac = hmacProvider.GenerateHmac(token.GetCsrfTokenBytes());
 }