DEV Community

loading...

How to securely send/receive key params in an .NET Core WebAPI and Javascript Application

Ravi Ranjan Pandey
Full-Stack Software Engineer, Technology Enthusiast, Loves Coding and Programming Languages. Crush on Algorithms
・3 min read

In an api its common to have some identifier keys to identify user details and process data accordingly. Its also common to take these details from either query parameters or headers or route path from client side.
However these apis will be rejected in the security audit process as they expose user data and has insecure object reference vulnerability, which can be maliciously exploited to get information of other users by tweaking these api parameters.
There are many ways to handle this security issue, however in this tutorial i will explain how to handle this by encrypting these params together into a single key and sending that in a header. I will also explain how to handle it at the api level using a middleware in .NET Core Api. Encryption is done in javascript to use in a client application and decryption is done in C# at the API level.
I have used AES Key-Based Encryption algorithm to achieve encryption and decryption.

Lets assume we have an salaries api with employeeid as param

api/salaries/getbyemployeeid?employeeid=1031

in this api, we are exposing an important key identifier employeeid and hence its exposed because anyone with some basic authentication can check details of another employee to avoid this first we will remove the query parameter.

api/salaries/getbyemployeeid

next we will generate an encrypted key using AES Encryption and then we will send that key as header.

Encryption in JavaScript

install the package npm install crypto-js


const CryptoJS = require('crypto-js');
function Encrypt(str) {
                 var KEY = "12345678900000001234567890000000";//32 bit
                 var IV = "1234567890000000";//16 bits
        var key = CryptoJS.enc.Utf8.parse(KEY);
        var iv = CryptoJS.enc.Utf8.parse(IV);

        var encrypted = '';

        var srcs = CryptoJS.enc.Utf8.parse(str);
        encrypted = CryptoJS.AES.encrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });

        return encrypted.ciphertext.toString();
    }
var encryptedEmployeeId = Encrypt("1031");
console.log(encryptedEmployeeId);
//result would be EF082204BF6F804099396A96CC7733F4

Enter fullscreen mode Exit fullscreen mode

Decryption in C#


public class EncryptDecrypt
{
    public static string AESDecryption(string input)
    {
        string AES_IV = "1234567890000000";//16 bits 
        string key = "12345678900000001234567890000000"; //32 bits
        byte[] inputBytes = HexStringToByteArray(input);
            byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 32));
            using AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider();
            aesAlg.Key = keyBytes;
            aesAlg.IV = Encoding.UTF8.GetBytes(AES_IV.Substring(0, 16));

            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            using MemoryStream msEncrypt = new MemoryStream(inputBytes);
            using CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read);
            using StreamReader srEncrypt = new StreamReader(csEncrypt);
            return srEncrypt.ReadToEnd();
    }

private static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }
}

Enter fullscreen mode Exit fullscreen mode

Send encrypted param in the header
I added a header named Request-Id
Request-Id : EF082204BF6F804099396A96CC7733F4

Adding a Request Middleware to grab the header value and Decrypt it.


public class RequestMiddleware
    {
        private readonly RequestDelegate _next;
        public RequestMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Headers.TryGetValue("Request-Id", out var requestid))
            {
                var employeeid = EncryptDecrypt.AESDecryption(requestid);     
            }

            await _next(context);
        }
    }

Enter fullscreen mode Exit fullscreen mode

Configure the Middleware before the middleware used for other apis to make it available and can be saved in a static variable.

app.UseMiddleware(typeof(RequestMiddleware));

Conclusion
So, in this tutorial i explained how can we send key based encrypted parameter in an api request in the header instead of sending directly and modified the api as shown initially.

Discussion (0)