Skip to content

Instantly share code, notes, and snippets.

@drovani
Last active February 18, 2022 10:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save drovani/df732f165d9735ad635707db1020d55d to your computer and use it in GitHub Desktop.
Save drovani/df732f165d9735ad635707db1020d55d to your computer and use it in GitHub Desktop.
Sample C# Code to Generate Shopify Multipass Url
string secret = "[shopify-multipass-secret]";
string store = "[shopify-store]";
var json = System.Text.Json.JsonSerializer.Serialize(new {
email = "[customer-email]",
created_at = DateTime.Now.ToString("O"),
identifier = "[customer-uid]",
//remote_ip = ""
});
var hash = System.Security.Cryptography.SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(secret));
var encryptionKey = new ArraySegment<byte>(hash, 0, 16).ToArray();
var signatureKey = new ArraySegment<byte>(hash, 16, 16).ToArray();
var initvector = new byte[16];
new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(initvector);
byte[] cipherData = new Func<byte[], byte[], byte[]>((iv, key) =>
{
byte[] encrypted;
using (var aes = System.Security.Cryptography.Aes.Create())
{
aes.Key = encryptionKey;
aes.IV = iv;
aes.Mode = System.Security.Cryptography.CipherMode.CBC;
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream ms = new MemoryStream())
using (System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(ms, encryptor, System.Security.Cryptography.CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(json);
}
encrypted = ms.ToArray();
}
}
return encrypted;
})(initvector, encryptionKey);
byte[] cipher = initvector.Concat(cipherData).ToArray();
byte[] signature = new HMACSHA256(signatureKey).ComputeHash(cipher);
string token = Convert.ToBase64String(cipher.Concat(signature).ToArray()).Replace("+", "-").Replace("/", "_");
string url = $"https://{store}.myshopify.com/account/login/multipass/{token}";
@drovani
Copy link
Author

drovani commented Feb 1, 2022

Garbage collection is a complicated topic, akin to cache invalidation. There's no perfect solution, everyone has an opinion, and nothing works universally.

Having said that, unless you have large, long-running applications, chances are that you'll never really need to worry about the intricacies of GC methodologies. When an app closes, garbage collection will typically clear up everything you forgot to dispose.

Wrapping an IDisposable in a using statement is a good practice with little downside. Assuming the class implements IDisposable according to best practice, the objects will all get disposed during the finalizer.

More about that can be found at CA1063: Implement IDisposable correctly.

@flyinmryan
Copy link

Thanks again for taking the time to explain your code. It really boggles my mind how inadequate and full of traps Shopify’s API documentation and development experience are. There are no shortage of questions on their community forum, but without answers to many of them it’s counterproductive. Your code makes sense now, and had you not posted this I would have probably given up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment