fireproofsocks
I’m working on an Elixir implementation of Shopify’s Multipass feature – it’s basically a single-sign-on (SSO) flow that lets your app handle authentication, and on success, it produces a URL that when clicked will cause a customer record to be upserted into Shopify. They include working examples of how to do this in PHP and Ruby, but I cannot make it work in Elixir.
You have to enable the feature and they give you a 32 character shared secret key.
# Example key from Shopify Admin
multipass_secret = "1234567890abcdef1234567890abcdef"
customer_data = %{
email: "test@test.shopify.com",
created_at: DateTime.to_iso8601(Timex.now()), # <-- the token will only be valid for a small timeframe around this timestamp.
}
key_material = :crypto.hash(:sha256, multipass_secret)
# Split the key into 2 binaries each containing exactly 16 bytes
<< encryption_key::binary-size(16), signature_key::binary-size(16) >> = key_material
customer_data_as_string = Jason.encode!(customer_data)
# Initialization Vector
ivec = :crypto.strong_rand_bytes(16)
to_add = 16 - rem(byte_size(customer_data_as_string), 16)
padded = customer_data_as_string <> :binary.copy(<<to_add>>, to_add)
cipher_text = ivec <> :crypto.block_encrypt(:aes_cbc128, encryption_key, ivec, padded)
signature = :crypto.hmac(:sha256, signature_key, cipher_text)
message = cipher_text <> signature
token = Base.encode16(message, case: :lower)
"https://yourstore.myshopify.com/account/login/multipass/#{token}"
Note that this feature is only available in Shopify Plus accounts.
Links I’ve been pouring over:
- crypto — OTP 29.0.2 (crypto 5.9)
- https://stackoverflow.com/questions/37629194/how-to-encrypt-and-decrypt-with-aes-cbc-128-in-elixir
Does anyone have some pointers on converting this? Thanks!
Trending in Questions
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
Hello,
I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind.
However, when I launch mix phx.server, I get an error...
New
I’m working on a small exercise involving update_in/3, and I came up with this solution:
data = %{
name: "Periodic Table",
category:...
New
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication):
toke...
New
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New
** (ArgumentError) expected :max_attempts to be a positive integer, got: {:@, [line: 10, column: 19], [{:max_attempts, [line: 10, column:...
New
Hello folks!
So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Other Trending Topics
Edit: 2026 May 15 - This post is archived.
Mob is alive!!
Main docs: mob v0.7.11 — Documentation
A bit of explanation for the slightly c...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
A little off-topic, but I feel like people here have a good head on their shoulders.
I used to be quite good at making software. Was luc...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Ninigi
Do you get a meaningful error? What exactly happens when you try this?
fireproofsocks
No error on generation, but when I click the link to head over to Shopify, I get a bad request error. Using the PHP or Ruby code samples results in a working link that logs me into the Shopify store.
Ninigi
Before diving too deep into this, can you try
EDIT
I took the provided ruby code on the Shopify documentation, replaced dynamic values with static values (the json string and
iv) and used the resulting token to set up a simple test.I think you already had it:
Just change
Base.encode16/2toBase.url_encode64/1fireproofsocks
WOW. That has to be the best typo I’ve made in weeks! Base 16?!? I was so focused on the hard parts of the crypto stuff that I didn’t pay attention to the last bit. THANK YOU!!
fireproofsocks
For the record, here is the complete working proof-of-concept code:
maz
It’s so easy to mess-up crypto.
NobbZ
Yeah. That might be the reason behind the first rule of the crypto club:
Ninigi
Good to hear you solved it
If you have some spare time, a pull request to implement multipass would be more than welcome!
fireproofsocks
Sure – the process does require that customer data be JSON encoded. Can you recommend how to nicely implement that as a dependency? Or should I restructure the input to make the user do the JSON encoding outside of your package?
Ninigi
the package already uses Poison for json processing, so I think you should not have to introduce a new dependency