Jeff
Jeff

Reputation: 55

Api design with authorization from one service to another

I am creating a Shopify app which has its own Shopify oAuth. I have built an external NodeJS application to handle all the settings, handling all the dashboard analytics, etc via api's.

I need to connect these two services together. Upon installing the application on Shopify I have an endpoint on my external service to create the shop in my table. Although now on I need to allow ONLY that store to be able to view their data / update it and not modify the request to get other stores information. Also not allow the public to view these endpoints.

I was thinking of generating an Api token on the NodeJS (external) application and saving it in the Shopify Database (Another database of stores), then passing it on every request and verifying it on the external application side. I like this approach but I also feel its not as secure since someone can steal a token.

[You also don't actually "create" an account, you just Install the app, and the app makes an Api request for a new "store" entry] I was thinking of using JWT for that but possibly can't.

Another option was combining the Api token and creating 1 admin user on the external NodeJS so that a Bearer token w/ the Api token need to be passed. This gives 1 extra layer of security since they would "need" to have this app install at least in Shopify.

What are some suggestions that I can look into?

Upvotes: 0

Views: 293

Answers (1)

Eric Haynes
Eric Haynes

Reputation: 5806

Shopify's docs recommend a number of libraries for using their OAuth, and I would recommend using one of those until you're more familiar with the OAuth workflow. They also supply a template project that already has this wired up in an express server. Depending on where you are with your external project, you might consider starting with that and moving your existing code into it, but if not, the web/middleware section will give you an example of what to do.

To answer your specific question, I think you might be misunderstanding how OAuth works, as you would likely not generate any tokens yourself. There are a lot of lengthy explanations out there (a few here: What exactly is OAuth (Open Authorization)?), but for a really basic rundown, let's first consider a really simple traditional authentication workflow:

  • user registers on your site, and you store their username and a hash of the password in a table such as users
  • when the user tries to log in, they send a username and password. You check this against your users table, and if it matches, you generate an auth token. You then store this token along with the username in a table such as auth_tokens
  • for subsequent requests, they include this auth token as a header. For every single request, you look up the token in the auth_tokens table, and if it's there (and hasn't expired), you assume the request comes from the username you stored with the token and restrict access accordingly

With OAuth, you're offloading all of that to a third party. This is oversimplified a bit, but effectively works like:

  • user registery with third-party
  • when the user tries to log in to your site, you redirect them to third-party, and they log in there
  • third-party gives them a token and redirects them back to your site
  • your app calls third-party with the token, and if it's valid, third-party gives you their username (and some other info). You trust third-party, so you take their word for it that the request comes from that user and restrict access accordingly

In the case of shopify, the "other info" will include the shop, and your app can then choose to only show them info for that shop.

https://github.com/Shopify/shopify-api-node/blob/main/src/auth/session/types.ts


EDIT based on comments: If I understand correctly, you mean that, after doing something in Shopify, you also want the same person to use your core application to update things in this external service WITHOUT Shopify in the middle, and you want to verify that it's the same person.

If so, your hesitation about the token is correct. You would essentially be handing out a password that works forever and storing it in an insecure place. There are 2 better options.

  1. I know NOTHING about this, but it does look like Shopify has an option to be an OAuth provider for your core application as well. https://shopify.dev/api/multipass. This is essentially the same as a "Log in with Google" option. This way, you're using Shopify's tokens for everything.

  2. Your application could have its own login, and you would need to associate your user with theirs. One easy way to do that would be using the email address. Nested in that session token you get from Shopify, you have the onlineAccessInfo:

export interface OnlineAccessInfo {
  expires_in: number;
  associated_user_scope: string;
  associated_user: {
    ...
    id: number;
    email: string;
    email_verified: boolean;
    ...
  };
}

You would need to keep a record of this info when requests come from Shopify. If they have verified the address (the email_verified field is true), and you have verified the address, then you can assume they're the same person. You could either require that they register on your site with the same email, or you could verify it separately if they did not.

Upvotes: 1

Related Questions