Skip to content
This repository has been archived by the owner on Jul 14, 2022. It is now read-only.

Fix part of #60 #61

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

Fix part of #60 #61

wants to merge 2 commits into from

Conversation

hpawe01
Copy link

@hpawe01 hpawe01 commented Mar 13, 2018

  • Tries to extract shop from the referer header, if not in query
  • Makes sure, that the shop from the session is the same as the shop performing the request

- Tries to extract shop from the `referer` header, if not in query
- Makes sure, that the shop from the session is the same as the shop performing the request
@hpawe01 hpawe01 changed the title Fix #60 Fix part of #60 Mar 13, 2018
Copy link
Contributor

@marutypes marutypes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some stylistic things, but the code looks sane. I'm going to open an issue to actually test this middleware.

@@ -1,8 +1,16 @@
module.exports = function withShop({ authBaseUrl } = {}) {
return function verifyRequest(request, response, next) {
const { query: { shop }, session, baseUrl } = request;
const { session, baseUrl } = request;
let shop = request.query.shop;
Copy link
Contributor

@marutypes marutypes Mar 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be a bit more idiomatic of the code style favouring immutability we have in this repo I'd maybe consider something a bit more like

const {session = {}, baseUrl, query} = request;
const {accessToken} = session;

const shop = shopFromReferrer(request.get('referrer')) || session.shop

if (accessToken) { 
  next();
  return;
}

if (shop) {
  response.redirect(`${authBaseUrl || baseUrl}/auth?shop=${shop}`);
  return;
}

response.redirect('/install');

Where we shove the regex logic into another function in scope.

function shopFromReferrer(referrer) {
  const results = referrer.match(/shop=([^&]+)/) ;
  return results && results[1]
}

@marutypes
Copy link
Contributor

Also thanks so much for contributing :)

@hpawe01
Copy link
Author

hpawe01 commented Mar 18, 2018

Thanks for the styling tips! I implemented them in the way you described.

Copy link
Contributor

@marutypes marutypes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great :)

@marutypes marutypes requested review from AWaselnuk and lopert March 19, 2018 18:21
@marutypes
Copy link
Contributor

@AWaselnuk @lopert either of you have any objections?

Copy link
Contributor

@AWaselnuk AWaselnuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks lovely. Thank you!

if (!referrer) {
return;
}
const result = referrer.match(/shop=([^&]+)/);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is concerning to me from a security perspective – could this allow an arbitrary user to log in as a given shop if they spoof the referrer?

The code as is wouldn't even require explicit spoofing – any referring URL with the shop parameter would be able to log in as the provided shop given that this shop has previously authed and we have an access token stored.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They need to have an access token in express's session, which means they've logged in before. We could also pull up the shop in question and check if the accessToken matches, which I opened an issue for. #64

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamiemtdwyer Actually the referrer is just another way to get the shop name. If an arbitrary user could log in as a given shop by spoofing the referrer, they could do it already at the moment by providing the GET parameter shop.

So this pull request is independent of the security issue you describe. As @TheMallen points out in #64 it is not the question how we determine, which shop is requested, but if the current session token matches the requested shop.

Copy link
Contributor

@marutypes marutypes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After talking to Jamie I think we actually need to can this.

We'll need to implement something similar to login_again_if_different_shop to properly handle multiple shops consistently with shopify_app.

I'm sorry. Thanks so much for the effort.

@hpawe01
Copy link
Author

hpawe01 commented Mar 26, 2018

Actually I see the same problem in this rails code as that one I want to fix with this pull request: to get the requesting shop, only params[:shop] is checked. We are ignoring the referrer as well
and so I guess with shopify_app we also have the problem when accessing a shopify app through multiple shops during one browser session.

Regarding your point, that the implementation should be similar to the rails app: I am no rails expert, but with this pull request the behavior looks more similar to the rails code than before. What the rails code does is:

  1. check if there is a session #L12
  2. if not redirect to login #L20
  3. if yes, check if the shop in the session is the same as the requesting #L30
  4. if not, clean the session and redirect to login #L33
  5. if yes, proceed

We do the same but in another order:

  1. check if there is a session and if the shop in the session is the same as the requesting #L7
  2. if yes proceed
  3. if no, redirect to login / install #L12 / #L17

The only thing we don't do is to reset the session. But I can add this, if you want:

\\ ...
if (accessToken && session.shop === shop) {
  next();
  return;
}

request.session.acessToken = null;
request.session.shop = null;
\\ ...

Don't know if that works though. And it is more part of #64 than #60.

But anyhow, as I said here, I think this pull request should be merged as it doesn't decreases the security and can be easily used as basis for #64.

@marutypes
Copy link
Contributor

@jamiemtdwyer does this assuage your fears?

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

Successfully merging this pull request may close these issues.

4 participants