예제 #1
0
        public string Unprotect(string protectedData, IDotvvmRequestContext context)
        {
            if (protectedData == null)
            {
                throw new ArgumentNullException(nameof(protectedData));
            }
            if (string.IsNullOrWhiteSpace(protectedData))
            {
                throw new ArgumentException("Value cannot be empty or whitespace only string.", nameof(protectedData));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // Construct protector with purposes
            var userIdentity    = ProtectionHelpers.GetUserIdentity(context);
            var requestIdentity = ProtectionHelpers.GetRequestIdentity(context);
            var protector       = this.protectionProvider.Create(PRIMARY_PURPOSE, userIdentity, requestIdentity);

            // Return unprotected view model data
            var dataToUnprotect = Convert.FromBase64String(protectedData);
            var unprotectedData = protector.Unprotect(dataToUnprotect);

            return(Encoding.UTF8.GetString(unprotectedData));
        }
예제 #2
0
        private const string KDF_LABEL_TOKEN = "DotVVM.Framework.Security.DefaultCsrfProtector.Token"; // Key derivation label for protecting token

        public string GenerateToken(IDotvvmRequestContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // Get SID
            var sid = this.GetOrCreateSessionId(context);

            // Get application key helper
            var keyHelper = new ApplicationKeyHelper(context.Configuration.Security);

            // Get token
            var userIdentity    = ProtectionHelpers.GetUserIdentity(context);
            var requestIdentity = ProtectionHelpers.GetRequestIdentity(context);
            var tokenData       = keyHelper.ProtectData(sid, KDF_LABEL_TOKEN, userIdentity, requestIdentity);

            // Return encoded token
            return(Convert.ToBase64String(tokenData));
        }
예제 #3
0
        public string GenerateToken(IDotvvmRequestContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // Get SID
            var sid = this.GetOrCreateSessionId(context);

            // Construct protector with purposes
            var userIdentity    = ProtectionHelpers.GetUserIdentity(context);
            var requestIdentity = ProtectionHelpers.GetRequestIdentity(context);
            var protector       = this.protectionProvider.Create(PURPOSE_TOKEN, userIdentity, requestIdentity);

            // Get token
            var tokenData = protector.Protect(sid);

            // Return encoded token
            return(Convert.ToBase64String(tokenData));
        }
예제 #4
0
        public void VerifyToken(IDotvvmRequestContext context, string token)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (string.IsNullOrWhiteSpace(token))
            {
                throw new SecurityException("CSRF protection token is missing.");
            }

            // Get application key helper
            var keyHelper = new ApplicationKeyHelper(context.Configuration.Security);

            // Get token
            var userIdentity    = ProtectionHelpers.GetUserIdentity(context);
            var requestIdentity = ProtectionHelpers.GetRequestIdentity(context);

            byte[] tokenSid;
            try
            {
                var tokenData = Convert.FromBase64String(token);
                tokenSid = keyHelper.UnprotectData(tokenData, KDF_LABEL_TOKEN, userIdentity, requestIdentity);
            }
            catch (Exception ex)
            {
                // Incorrect Base64 formatting of crypto protection error
                throw new SecurityException("CSRF protection token is invalid.", ex);
            }

            // Get SID from cookie and compare with token one
            var cookieSid = this.GetOrCreateSessionId(context);

            if (!cookieSid.SequenceEqual(tokenSid))
            {
                throw new SecurityException("CSRF protection token is invalid.");
            }
        }
예제 #5
0
        public void VerifyToken(IDotvvmRequestContext context, string token)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (string.IsNullOrWhiteSpace(token))
            {
                throw new SecurityException("CSRF protection token is missing.");
            }

            // Construct protector with purposes
            var userIdentity    = ProtectionHelpers.GetUserIdentity(context);
            var requestIdentity = ProtectionHelpers.GetRequestIdentity(context);
            var protector       = this.protectionProvider.Create(PURPOSE_TOKEN, userIdentity, requestIdentity);

            // Get token
            byte[] tokenSid;
            try
            {
                var tokenData = Convert.FromBase64String(token);
                tokenSid = protector.Unprotect(tokenData);
            }
            catch (Exception ex)
            {
                // Incorrect Base64 formatting of crypto protection error
                throw new SecurityException("CSRF protection token is invalid.", ex);
            }

            // Get SID from cookie and compare with token one
            var cookieSid = this.GetOrCreateSessionId(context, canGenerate: false); // should not generate new token

            if (!cookieSid.SequenceEqual(tokenSid))
            {
                throw new SecurityException("CSRF protection token is invalid.");
            }
        }
예제 #6
0
        public string Unprotect(string protectedData, IDotvvmRequestContext context)
        {
            if (protectedData == null)
            {
                throw new ArgumentNullException(nameof(protectedData));
            }
            if (string.IsNullOrWhiteSpace(protectedData))
            {
                throw new ArgumentException("Value cannot be empty or whitespace only string.", nameof(protectedData));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // Get application key helper
            var keyHelper = new ApplicationKeyHelper(context.Configuration.Security);

            // Unprotect serialized data
            var userIdentity    = ProtectionHelpers.GetUserIdentity(context);
            var requestIdentity = ProtectionHelpers.GetRequestIdentity(context);

            return(keyHelper.UnprotectString(protectedData, KDF_LABEL, userIdentity, requestIdentity));
        }
예제 #7
0
        private byte[] GetOrCreateSessionId(IDotvvmRequestContext context, bool canGenerate = true)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var sessionIdCookieName = GetSessionIdCookieName(context);

            if (string.IsNullOrWhiteSpace(sessionIdCookieName))
            {
                throw new FormatException("Configured SessionIdCookieName is missing or empty.");
            }

            // Get cookie manager
            var mgr = new ChunkingCookieManager(); // TODO: Make this configurable

            // Construct protector with purposes
            var userIdentity    = ProtectionHelpers.GetUserIdentity(context);
            var requestIdentity = ProtectionHelpers.GetRequestIdentity(context);
            var protector       = this.protectionProvider.Create(PURPOSE_SID);

            // Get cookie value
            var sidCookieValue = mgr.GetRequestCookie(context.GetOwinContext(), sessionIdCookieName);

            if (!string.IsNullOrWhiteSpace(sidCookieValue))
            {
                // Try to read from cookie
                try
                {
                    var protectedSid = Convert.FromBase64String(sidCookieValue);
                    var sid          = protector.Unprotect(protectedSid);
                    return(sid);
                }
                catch (Exception ex)
                {
                    // Incorrect Base64 formatting of crypto protection error
                    // Generate new one or thow error if can't
                    if (!canGenerate)
                    {
                        throw new SecurityException("Value of the SessionID cookie is corrupted or has been tampered with.", ex);
                    }
                    // else suppress error and generate new SID
                }
            }

            // No SID - generate and protect new one

            if (canGenerate)
            {
                var rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
                var sid = new byte[SID_LENGTH];
                rng.GetBytes(sid);
                var protectedSid = protector.Protect(sid);

                // Save to cookie
                sidCookieValue = Convert.ToBase64String(protectedSid);
                mgr.AppendResponseCookie(
                    context.GetOwinContext(),
                    sessionIdCookieName,                                // Configured cookie name
                    sidCookieValue,                                     // Base64-encoded SID value
                    new Microsoft.Owin.CookieOptions
                {
                    HttpOnly = true,                                   // Don't allow client script access
                    Secure   = context.HttpContext.Request.IsHttps     // If request goes trough HTTPS, mark as secure only
                });

                // Return newly generated SID
                return(sid);
            }
            else
            {
                throw new SecurityException("SessionID cookie is missing, so can't verify CSRF token.");
            }
        }