Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an oAuth HMAC authentication #71

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

humancopy
Copy link
Contributor

This adds the ability to authenticate the request from Shopify using the HMAC param. I also modified the readme to reflect this change.

@humancopy humancopy force-pushed the oauth branch 2 times, most recently from 639e71e to c95e4b8 Compare April 11, 2019 17:23
…asier to make a pipeline and make sure the requests are authenticated.
@Ninigi
Copy link
Collaborator

Ninigi commented Apr 12, 2019

As always, thank you for contributing 👍

Could you move the HMAC auth into its own module?

There is a problem with authenticating hmac in plug based applications, because some plugs (json parse for example) consume the original request body, and the params map is not in the same order as the original params, so the hmac comes out different. This is no problem with query params, but validating webhooks can be tricky to say the least. You can try sorting the params, but iirc if you receive a list, or nested params, it is almost impossible to sort them back into the original format.
So your best bet would be to read the original body - which requires the plug to be called before any other plug that could consume the body - and put the original body back into the plug after verification.

This is fine for a first draft, but if you want to address the issue I just mentioned, feel free to take some time. If not, let me know and I will take a closer look at the rest 😄

@humancopy
Copy link
Contributor Author

Yes I actually ran into a problem while using this with parameters coming in for order ids. So I'll smooth that out :)

Where did you have in mind to put the HMAC auth validation? I thought it actually fits in the oAuth module because it's only for oAuth, they have a different authentication scheme for Webhooks.

@Ninigi
Copy link
Collaborator

Ninigi commented Apr 12, 2019

Yes I actually ran into a problem while using this with parameters coming in for order ids. So I'll smooth that out :)

👍

Where did you have in mind to put the HMAC auth validation? I thought it actually fits in the oAuth module because it's only for oAuth, they have a different authentication scheme for Webhooks.

Maybe something like HMACAuth and then we could pattern match on the different schemes? Just for separation of concerns, I think the hmac validation logic should have it's own module. Does not have to be exactly this, but:

HMACAuth.check(params, :oauth)
# and
HMACAuth.check(params, :webhook)

@humancopy
Copy link
Contributor Author

humancopy commented Apr 12, 2019

Ok cool, I'll work out some module for the auth ;)

As for the ids parameter, I found that it's a specific issue with bulk menu items, and there is a suggested solution though I haven't managed to make it work validate ... It seems Shopify is quite vague about this scenario:

https://community.shopify.com/c/Shopify-APIs-SDKs/HMAC-calculation-vs-ids-arrays/m-p/261154

@humancopy
Copy link
Contributor Author

humancopy commented Apr 12, 2019

I fixed the issue with the ids parameter in 1ed38f8

It's crazy Shopify don't URI encode it 😮

@nsweeting
Copy link
Owner

I would maybe try and keep the PR focused on a simple hmac authentication method. One that could be applied against both oauth and webhooks.

Something akin to Shopify.HMAC.authenticate(secret, raw_body) - or something like that. The logic surrounding the details for auth'ing oauth vs webhooks can be kept in their respective modules.

One thing to be aware of is that we need to prevent timing attacks. I've typically done this with Plug.Crypto.secure_compare/2. But we could probably just copy the code to remove the need to add the dependency.

Typically I've been using the ueberauth_shopify library for performing oauth. Ueberuath has become the elixir standard for oauth. Couple thoughts:

  1. We could add ueberauth support in this library. The actual hmac authentication could be performed within that context then (using the HMAC module).
  2. A PR could be made on that library, as I dont believe it performs hmac auth at the moment...

@humancopy
Copy link
Contributor Author

I don't know if it's a good idea to add a dependency for ueberauth_shopify just to make the authentication. Unless I'm missing something why it's good to use that instead of the code already in the lib I'd be happy to understand the benefits :)

As for HMAC, it's for authenticating all Shopify requests and not just the preliminary auth one so I think it's better to implement it in the library. Again, please enlighten me if I missed something ;)

I'll try to implement the module Shopify.HMAC.authenticate this week, if times allows me. Maybe it's better I open a new PR for it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants