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!

Tuesday, October 13, 2015

CRM ISV Module Creation


Are you planning to create any ISV module which is able to connect to CRM?


How can you refactor the code of  that module in such a way taht, it can connect to other CRM's as well- like siebel crm, oracle crm, custom build crm.

This post may help you for that. Here is the starting point. You can build further on top of this.:

Let us have base abstract class called BusinessEntity. 

This base class has an array of  attributes which can store key value pair.

SetAttributeValue and GetAttributeValue will help you to store and retrieve properties.
object this[string attributeName] will help you to pass attribute collection on the instance object.





public abstract class BusinesEntity
    {
     
        public AttributeCollection _attributes;

      
        public bool Contains(string attributeName)
        {
            return this.Attributes.Contains(attributeName);

        }
       
        public object this[string attributeName]
        {
            get
            {
                return this.Attributes[attributeName];
            }
            set
            {
                this.Attributes[attributeName] = value;
            }
        }
        public AttributeCollection Attributes
        {
            get
            {
                if (this._attributes == null)
                {
                    this._attributes = new AttributeCollection();
                }
                return this._attributes;
            }
            set
            {
                this._attributes = value;
            }
        }

        public virtual T GetAttributeValue<T>(string attributeLogicalName)
        {
            object attributeValue = this.GetAttributeValue(attributeLogicalName);
            if (attributeValue == null)
            {
                return default(T);
            }
            return (T)attributeValue;
        }
        private object GetAttributeValue(string attributeLogicalName)
        {
            if (string.IsNullOrWhiteSpace(attributeLogicalName))
            {
                throw new ArgumentNullException("attributeLogicalName");
            }
            if (!this.Contains(attributeLogicalName))
            {
                return null;
            }
            return this[attributeLogicalName];
        }
        protected virtual void SetAttributeValue(string attributeLogicalName, object value)
        {
            if (string.IsNullOrWhiteSpace(attributeLogicalName))
            {
                throw new ArgumentNullException("attributeLogicalName");
            }
            this[attributeLogicalName] = value;
        }
       
       
    }


public class AttributeCollection : DataCollection<string,object>
    {

    }

public abstract class DataCollection<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
    {
        private IDictionary<TKey, TValue> _innerDictionary;
        private bool _isReadOnly;

        protected internal DataCollection()
        {
            this._innerDictionary = new Dictionary<TKey, TValue>();
        }

        public void Add(KeyValuePair<TKey, TValue> item)
        {
            this.CheckIsReadOnly();
            this._innerDictionary.Add(item);
        }

        public void Add(TKey key, TValue value)
        {
            this.CheckIsReadOnly();
            this._innerDictionary.Add(key, value);
        }

        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)
        {
            if (items != null)
            {
                this.CheckIsReadOnly();
                ICollection<KeyValuePair<TKey, TValue>> is2 = this._innerDictionary;
                foreach (KeyValuePair<TKey, TValue> pair in items)
                {
                    is2.Add(pair);
                }
            }
        }

        public void AddRange(params KeyValuePair<TKey, TValue>[] items)
        {
            this.CheckIsReadOnly();
            this.AddRange((IEnumerable<KeyValuePair<TKey, TValue>>)items);
        }

        private void CheckIsReadOnly()
        {
            if (this.IsReadOnly)
            {
                throw new InvalidOperationException("The collection is read-only.");
            }
        }

        public void Clear()
        {
            this.CheckIsReadOnly();
            this._innerDictionary.Clear();
        }

        internal void ClearInternal()
        {
            this._innerDictionary.Clear();
        }

        public bool Contains(KeyValuePair<TKey, TValue> key)
        {
            return this._innerDictionary.Contains(key);
        }

        public bool Contains(TKey key)
        {
            return this._innerDictionary.ContainsKey(key);
        }

        public bool ContainsKey(TKey key)
        {
            return this._innerDictionary.ContainsKey(key);
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            this._innerDictionary.CopyTo(array, arrayIndex);
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return this._innerDictionary.GetEnumerator();
        }



        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            this.CheckIsReadOnly();
            return this._innerDictionary.Remove(item);
        }

        public bool Remove(TKey key)
        {
            this.CheckIsReadOnly();
            return this._innerDictionary.Remove(key);
        }

        internal bool RemoveInternal(TKey key)
        {
            return this._innerDictionary.Remove(key);
        }

        internal void SetItemInternal(TKey key, TValue value)
        {
            this._innerDictionary[key] = value;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this._innerDictionary.GetEnumerator();
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            return this._innerDictionary.TryGetValue(key, out value);
        }

        public int Count
        {
            get
            {
                return this._innerDictionary.Count;
            }
        }

        public virtual bool IsReadOnly
        {
            get
            {
                return this._isReadOnly;
            }
            internal set
            {
                this._isReadOnly = value;
            }
        }

        public virtual TValue this[TKey key]
        {
            get
            {
                return this._innerDictionary[key];
            }
            set
            {
                this.CheckIsReadOnly();
                this._innerDictionary[key] = value;
            }
        }

        public ICollection<TKey> Keys
        {
            get
            {
                return this._innerDictionary.Keys;
            }
        }

        public ICollection<TValue> Values
        {
            get
            {
                return this._innerDictionary.Values;
            }
        }
    }

Now Let us consume this abstract class in on sample class called Master record.
For each attribute you can set and get values by using GetAttributeValue and SetAttributeValue methods.
  public class MasterRecord: BusinesEntity
    {

        public virtual Guid Id
        {
            get { return this.GetAttributeValue<Guid>("id"); }
            set { this.SetAttributeValue("id", value); }
        }

        public virtual string SchemaName
        {
            get { return this.GetAttributeValue<string>("schemaName"); }
            set { this.SetAttributeValue("schemaName", value); }
        }
        public virtual string Content
        {
            get { return this.GetAttributeValue<string>("content"); }
            set { this.SetAttributeValue("content", value); }
        }
        public virtual bool IsDefault
        {
            get { return this.GetAttributeValue<bool>("isdefault"); }
            set { this.SetAttributeValue("isdefault", value); }
        }

        public virtual status Status
        {
            get { return this.GetAttributeValue<status>("status"); }
            set { this.SetAttributeValue("status", value); }
        }
        public virtual TypeOfPreferance TypeOfPreferance
        {
            get { return this.GetAttributeValue<TypeOfPreferance>("typeofpreferance"); }
            set { this.SetAttributeValue("typeofpreferance", value); }
        }

        public virtual bool IsOptIn
        {
            get { return this.GetAttributeValue<bool>("isoptin"); }
            set { this.SetAttributeValue("isoptin", value); }
        }
      
       
    }
You are done with basic structure CRM entity type implementation.

Now let us try to use this Master record class.
You can use it

          MasterRecord mObj = new MasterRecord();
           mObj["Id"] = new Guid();

            //You can pass attributes to the collection in two ways

            //Late Bind style
           mObj["SchemaName"] = "TestSchemaName";
           mObj["Status"] = 1;

            //Early bind style
           mObj.IsDefault = true;
           mObj.IsOptIn = false;

Look at the object. You can see a replica of CRM entity type




Like MasterRecord, you can have list of business entities as per your module. These business entities can map with equivalent entities of any CRM. Using factory pattern for Data Provider, you can connect to any type of CRM. I will post it in future. Stay Tune!
  

Happy Coding!