Thursday, November 5, 2015

url with token parameter



Hi Nice day for you, Today I thought before starting my work Let me pass some information to google search content.

I got lot of help from Google search to do my work easier. Sometime I think myself as selfish not contributing back to the search content. So some bit of information which might help somebody else.

Okay.. Yesterday my boss asked me, we need to send a token while we send mails to customers either using Direct CRM features or third party using extracted list from CRM.

That token should help customer to do some action in CRM without much authentication issues. Like... they can change their phone number by clicking a link. They were able to update their marketing mail preferences with the help of URL and so on...

Indeed there are lot of concerns while we go to security team with the solution. They are asking about, Validity of token, Guest authentication, Defense against reply attacks, Defense against identifier misuse, Defense against Man in middle attack blah blah blah…. :-)


I got confused about the solution as always. Does it have SAML Token, Web token, Identify provider required, Encryption required, Counter required, time stamp required.. Lot of thoughts.

At last some solution which worked for me. may be it has some issues, If you are expert on it, please comment.  That will help me.

So ... Created a Function which will provide me a URL If I pass an ID and KeY. Internally it is using encryption


public string DoEncryptedUrl(string PlainText, string Key)
        {
            String EncryptedString = "";
            if (PlainText == null || PlainText.Length <= 0)
                throw new ArgumentNullException("CipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            byte[] IV = GenerateRandomNumber(16);

            #region Adding Time Stamp
            DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
            TimeSpan ts = DateTime.UtcNow - epochStart;
            string stamp = Convert.ToUInt64(ts.TotalDays).ToString();
            #endregion

            //Create the token text appending Time Stamp
            string TempText = "text=" + PlainText + "&stamp=" + stamp;

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = System.Text.ASCIIEncoding.ASCII.GetBytes(Key);
                aesAlg.IV = IV;
                ICryptoTransform Encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEnrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEnrypt, Encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter srEecrypt = new StreamWriter(csEncrypt))
                        {
                            srEecrypt.Write(TempText);
                        }
                        EncryptedString = Convert.ToBase64String(msEnrypt.ToArray());
                    }
                }

            }

            return "token=" + EncryptedString + "&iv=" + Convert.ToBase64String(IV);


        }




This function will provide Encrypted url token content which can append to the URL while sending email. You can utilize this function anywhere.

Yes, you can attach this function as part of your work flow assembly and utilize the value in email templates in CRM. It can be service utilized by JS. It can be part of ETL program, so that you can process bulk data …..

Now we have to decrypt it.


Here is the method which I used

        public string DoDecryptionUrl(string CipherText, string Key)
        {
            String Originaltext = "";
            if (CipherText == null || CipherText.Length <= 0)
                throw new ArgumentNullException("CipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");

            //Getting Encrypted Token & iv separte
            NameValueCollection QueryString = FillFromString(CipherText);

            if (QueryString["iv"] == null || QueryString["iv"].Length <= 0)
                throw new ArgumentNullException("IV");

            //Reverse URL ezcape characters
            // QueryString["token"] = QueryString["token"].Replace('+', '/');
            byte[] encrypteddata = Convert.FromBase64String(QueryString["token"]);
            byte[] IV = Convert.FromBase64String(QueryString["iv"]);

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = System.Text.ASCIIEncoding.ASCII.GetBytes(Key);
                //aesAlg.Key = System.Text.ASCIIEncoding.ASCII.GetBytes("Informat");
                aesAlg.IV = IV; ;

                // aesAlg.Padding = PaddingMode.None;
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msDecrypt = new MemoryStream(encrypteddata))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            Originaltext = srDecrypt.ReadToEnd();
                        }
                    }
                }

                //Getting Decrypted Token as text and stamp
                NameValueCollection OriginaltextCollection = FillFromString(Originaltext);

                //Validating Time Stamp. Token will have 3 days validity
                DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
                TimeSpan ts = DateTime.UtcNow - epochStart;
                if ((Convert.ToUInt64(OriginaltextCollection["stamp"])) - (Convert.ToUInt64(ts.Days)) > 3)
                {
                    throw new TimeoutException("Token Time Out");
                }
                else
                {
                    return OriginaltextCollection["text"];
                }
            }

        }






Oh sorry! I forgot to add an identifier for which entity is encrypted. I think you can manage it. I will update it later. Time to start my regular work:-)

Happy Coding!


Look. Send your friends a note every now and then which can save their time and enjoy a coffee with somebody :-)


They need to know you care about them. Share!