How to Encrypt Cookies in ASP.NET Core MVC

SPONSOR AD

How to Encrypt Cookies in ASP.NET Core MVC

In this article, I will discuss How to Encrypt Cookies in ASP.NET Core MVC Applications with Examples. Please read our previous article discussing Cookies in ASP.NET Core MVC.

Encrypt Cookies in ASP.NET Core MVC

Encrypting cookies in ASP.NET Core MVC is essential for enhancing the security of your application. This ensures that sensitive information within cookies cannot be easily read or tampered with by unauthorized users. ASP.NET Core provides built-in mechanisms to facilitate cookie encryption. Using Data Protection API, we can encrypt the cookies in an ASP.NET Core MVC application:

What is Data Protection API?

The primary goal of the Data Protection API is to protect sensitive data, especially when it needs to be temporarily stored in an insecure location, like in cookies or form fields. Common use cases include protecting authentication tokens, session states, or any other sensitive information that must be preserved between requests.

How to Use Data Protection API in ASP.NET Core MVC?

ASP.NET Core uses the Data Protection API to provide cookie encryption. You generally do not need to manually encrypt cookies, as the framework handles it for you. But, if you create custom cookies, you must manually handle the encryption. You need to configure the Data Protection API in your Program.cs file as follows:

SPONSOR AD

builder.Services.AddDataProtection();

How do you encrypt custom cookies in ASP.NET Core MVC?

If you are creating custom cookies and want to ensure they are encrypted, you need to manually use the Data Protection API. So, create a class file with the name MyCookieService.cs and then copy and paste the following code:

using Microsoft.AspNetCore.DataProtection;
namespace SampleMVCWeb.Models
{
    public class MyCookieService
    {
        private readonly IDataProtector _protector;

        public MyCookieService(IDataProtectionProvider dataProtectionProvider)
        {
            //MyCookieProtector must be a unique string value for each Data Protection Provider
            _protector = dataProtectionProvider.CreateProtector("MyCookieProtector");
        }

        //This method will convert the Plain Data to Encrypted value
        public string Protect(string cookieValue)
        {
            return _protector.Protect(cookieValue);
        }

        //This method will convert the Encrypted Data to Plain value
        public string Unprotect(string protectedCookieValue)
        {
            return _protector.Unprotect(protectedCookieValue);
        }
    }
}

In ASP.NET Core, the Data Protection API provides a way to encrypt and decrypt data, including cookies. The CreateProtector, Protect, and Unprotect methods are key to this process.

  • CreateProtector Method: The CreateProtector method creates an instance of IDataProtector, which is then used to encrypt and decrypt data. You need to specify a purpose string when calling CreateProtector, which acts as a way to isolate protectors from each other.
  • Protect Method: The Protect method is used to encrypt data. The Protect method is used to encrypt data. You need to pass the plaintext data to this method, which returns the encrypted data.
  • Unprotect Method: The Unprotect method decrypts encrypted data with the Protect method. It will throw an exception if the data cannot be decrypted (e.g. if it has been tampered with or the protector was created for a different purpose).
Storing Cookies

When storing cookies in the response header, use the encrypted value. First, encrypt the value using DataProtector and then store the encrypted value in the Cookies. The syntax to encrypt the cookie is given below:

//Encrypt the Value using Data Protection API
string encryptedValue = myCookieService.Protect("Cookie Value");
//Store the Encrypted Cookie Value in the Response Header
Response.Cookies.Append("myCookie", encryptedValue, cookieOptions);
Reading Cookies

When reading the cookie, decrypt the value. First, read the encrypted value from the cookie and then use the DataProtector to decrypt the value. The syntax to decrypt the cookie is given below:

//Fetch the Encrypted Cookie Value from the Response Header
string encryptedValue = Request.Cookies["myCookie"];
//Decrypt the Encryoted Value using the Data Protection API
string decryptedValue = myCookieService.Unprotect(encryptedValue);
Configuring the Service:

Next, we need to configure the MyCookieService within the built-in dependency injection container. Registering a service without an interface in ASP.NET Core’s dependency injection (DI) system is straightforward. So, please add the following statement to the program.cs class file. Here, you need to pass the concrete class name to the AddSingleton method.

builder.Services.AddSingleton<MyCookieService>();

SPONSOR AD
Modifying Home Controller:

Next, modify the Home Controller as follows. First, we inject the MyCookieService instance through the constructor, and then, using this MyCookieService instance, we encrypt and decrypt the cookies. Further, we have stored the retrieved cookie values in the ViewBag, which will be displayed in the UI. This is because we don’t want to write the logic to fetch the encrypted data from the cookie and decrypt the value using data protected in the View file.

using Microsoft.AspNetCore.Mvc;
using SampleMVCWeb.Models;
namespace SampleMVCWeb.Controllers
{
    public class HomeController : Controller
    {
        const string CookieUserId = "UserId";
        const string CookieUserName = "UserName";
        MyCookieService _myCookieService;
        public HomeController(MyCookieService myCookieService)
        {
            _myCookieService = myCookieService;
        }

        public IActionResult Index()
        {
            //Let us assume the User is logged in and we need to store the user information in the cookie
            var cookieOptions = new CookieOptions
            {
                HttpOnly = true,
                Secure = true,
                SameSite = SameSiteMode.Strict,
                Expires = DateTime.Now.AddDays(7)
            };

            //Encrypt the Cookie Value
            string encryptedUserId = _myCookieService.Protect("1234567");
            //Store the Encrypted value in the Cookies Response Header
            Response.Cookies.Append(CookieUserId, encryptedUserId, cookieOptions);

            //Encrypt the Cookie Value
            string encryptedUserName = _myCookieService.Protect("pranaya@dotnettutotials.net");
            //Store the Encrypted value in the Cookies Response Header
            Response.Cookies.Append(CookieUserName, encryptedUserName, cookieOptions);

            //If you are coming to this page later,
            //it will also fetch the data from the Cookies Response Header
            string? encryptedUserNameValue = Request.Cookies[CookieUserName];
            if (encryptedUserNameValue != null)
            {
                ViewBag.UserName = _myCookieService.Unprotect(encryptedUserNameValue);
            };

            string? encryptedUserIdValue = Request.Cookies[CookieUserId];
            if (encryptedUserIdValue != null)
            {
                ViewBag.UserId = Convert.ToInt32(_myCookieService.Unprotect(encryptedUserIdValue));
            }

            return View();
        }

        public string About()
        {
            try
            {
                string? UserName = null;
                //Fetch the Encrypted Cookie from the Request Header
                string? encryptedUserNameValue = Request.Cookies[CookieUserName];
                if (encryptedUserNameValue != null)
                {
                    //Decrypt the Encrypted Value
                    UserName = _myCookieService.Unprotect(encryptedUserNameValue);
                };

                int? UserId = null;
                //Fetch the Encrypted Cookie from the Request Header
                string? encryptedUserIdValue = Request.Cookies[CookieUserId];
                if (encryptedUserIdValue != null)
                {
                    //Decrypt the Encrypted Value
                    UserId = Convert.ToInt32(_myCookieService.Unprotect(encryptedUserIdValue));
                }
                
                string Message = $"UserName: {UserName}, UserId: {UserId}";
                return Message;
            }
            catch (Exception ex)
            {
                return $"Error Occurred: {ex.Message}";
            }
        }

        public IActionResult Privacy()
        {
            //Fetch the Encrypted Cookie from the Request Header
            string? encryptedUserNameValue = Request.Cookies[CookieUserName];
            if (encryptedUserNameValue != null)
            {
                //Store the Decrypted Value in the ViewBag which we will display in the UI
                ViewBag.UserName = _myCookieService.Unprotect(encryptedUserNameValue);
            };

            //Fetch the Encrypted Cookie from the Request Header
            string? encryptedUserIdValue = Request.Cookies[CookieUserId];
            if (encryptedUserIdValue != null)
            {
                //Store the Decrypted Value in the ViewBag which we will display in the UI
                ViewBag.UserId = Convert.ToInt32(_myCookieService.Unprotect(encryptedUserIdValue));
            }
            return View();
        }

        public string DeleteCookie()
        {
            // Delete the Cookie From the Response Header, i.e., from the Browser.
            Response.Cookies.Delete(CookieUserId);
            Response.Cookies.Delete(CookieUserName);

            return "Cookies are Deleted";
        }
    }
}
CookieOptions Class in ASP.NET Core MVC
  • HttpOnly: The HttpOnly property specifies whether the cookie should be accessible only by the server. When set to true, the cookie cannot be accessed through client-side scripts. This is an important security feature that helps prevent cross-site scripting (XSS) attacks by not allowing client-side script access to the cookie. Default Value: false
  • Secure: The Secure property indicates that the cookie should be sent only over HTTPS. This security measure helps prevent attackers from intercepting the cookie in a man-in-the-middle attack. Default Value: false
  • SameSite: The SameSite property controls the same-site and cross-site cookie-sending behavior. It helps to protect against cross-site request forgery (CSRF) attacks. Default Value: SameSiteMode.Lax (Note: This can vary based on the version of ASP.NET Core and browser behavior.)
  • Expires: The Expires property sets the expiration date and time for the cookie. After this time, the cookie will no longer be sent to the server. This property is essential for controlling the lifecycle of your cookie. Default Value: null. By default, cookies are session cookies, which means they last only as long as the browser session.
Modifying Index.cshtml View
@{
    ViewData["Title"] = "Home Page";
}

<div class="text-left">
    <b>User Name:</b> @ViewBag.UserName
    <br />
    <b>User Id:</b> @ViewBag.UserId
</div>
Modifying Privacy.cshtml View
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<div class="text-left">
    <b>User Name:</b> @ViewBag.UserName
    <br />
    <b>User Id:</b> @ViewBag.UserId
</div>

With the above changes in place, run the application, and now you should see the cookies are transmitted over the network in encrypted format, as shown in the below image:

How to Encrypt Cookies in ASP.NET Core MVC Applications with Examples

Configuring Cookie Options Globally:

If you want to store the cookies using multiple action methods and you want multiple action methods to follow the same set of cookie option settings, then you can move such settings to the Program.cs class file. So, please add the following code to the Program.cs class file:

builder.Services.ConfigureApplicationCookie(options =>
{
    // Cookie settings
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.IsEssential = true; // Make the cookie essential
    options.Cookie.Expiration = TimeSpan.FromDays(1);
});

Now, you need to use the other version of the Append method to set the cookie, which does not take the cookie option object. So, modify the Index action method of the Home Controller class as follows:

public IActionResult Index()
{
    //Let us assume the User is logged in and we need to store the user information in the cookie
    //var cookieOptions = new CookieOptions
    //{
    //    HttpOnly = true,
    //    Secure = true,
    //    SameSite = SameSiteMode.Strict,
    //    Expires = DateTime.Now.AddDays(7)
    //};

    //Encrypt the Cookie Value
    string encryptedUserId = _myCookieService.Protect("1234567");
    //Store the Encrypted value in the Cookies Response Header
    //Response.Cookies.Append(CookieUserId, encryptedUserId, cookieOptions);
    Response.Cookies.Append(CookieUserId, encryptedUserId);

    //Encrypt the Cookie Value
    string encryptedUserName = _myCookieService.Protect("pranaya@dotnettutotials.net");
    //Store the Encrypted value in the Cookies Response Header
    //Response.Cookies.Append(CookieUserName, encryptedUserName, cookieOptions);
    Response.Cookies.Append(CookieUserName, encryptedUserName);

    //If you are coming to this page later,
    //it will also fetch the data from the Cookies Response Header
    string? encryptedUserNameValue = Request.Cookies[CookieUserName];
    if (encryptedUserNameValue != null)
    {
        ViewBag.UserName = _myCookieService.Unprotect(encryptedUserNameValue);
    };

    string? encryptedUserIdValue = Request.Cookies[CookieUserId];
    if (encryptedUserIdValue != null)
    {
        ViewBag.UserId = Convert.ToInt32(_myCookieService.Unprotect(encryptedUserIdValue));
    }

    return View();
}

With the above changes in place, run the application, and you should see that the application works as expected.

When should you use encrypted cookies in ASP.NET Core MVC?

Encrypted cookies in ASP.NET Core MVC are useful in scenarios where you need to store sensitive information in cookies while ensuring that it remains secure and protected from tampering or unauthorized access. Here are some specific instances when you might want to use encrypted cookies:

  • Storing Sensitive Information: If you need to store sensitive data, such as personal identifiers or preferences, that should not be exposed or manipulated by the client, encrypting the cookies adds an extra layer of security.
  • Preventing Tampering: Encrypted cookies help ensure that the data stored within them cannot be tampered with. Since the cookie content is encrypted, any modifications made by the client would invalidate the cookie.
  • Maintaining Integrity and Confidentiality: When the integrity and confidentiality of the data are crucial, encrypted cookies are the way to go. They ensure that unauthorized parties can neither read nor alter the data.
  • Regulatory Compliance: In some cases, regulations such as GDPR or HIPAA may require that any personal or sensitive data transmitted over the internet must be encrypted. Using encrypted cookies helps in meeting these compliance requirements.
  • Cross-Site Request Forgery (CSRF) Protection: While not a direct method for CSRF protection, using encrypted cookies can contribute to a more secure application by ensuring that critical data used in CSRF tokens cannot be tampered with.
  • Enhancing Application Security: Encrypted cookies are part of a broader approach to securing web applications. They should be used alongside other security practices like HTTPS, secure cookie attributes, and proper session management.
Notes:
  • Always ensure your application is running over HTTPS when dealing with secure cookies.
  • Regularly review your cookie and data protection policies to ensure they comply with the latest security standards.
  • Be mindful of the size limit of cookies (generally 4KB). Encrypting data will increase its size.

In the next article, I will discuss Persistent vs Non-Persistent Cookies in ASP.NET Core MVC Applications with Examples. In this article, I try to explain How to Encrypt Cookies in ASP.NET Core MVC Applications with Examples. I hope you enjoy this article on encrypting cookies in the ASP.NET Core MVC.

SPONSOR AD
SPONSOR AD

Leave a Reply

Your email address will not be published. Required fields are marked *