Api design with authorization from one service to another - node.js

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?

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.
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.
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.

Related

Azure Active Directory add custom data to Oauth2 token

I'm using the auth endpoint https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token programmatically (Nodejs) for getting back a token that will be used against my API. I have everything properly configured to send the request using a "Client secret" I setup on the Azure Portal - App registration service.
This issues a valid token that I can later check with the help of the Passport azure AD npm library. However I've been looking for a way of somehow adding more metadata to that token (i.e. a custom user name) so that when it gets validated and parsed by my server upon future requests I can extract this information.
When issuing tokens using a frontend application library (like msal) I have access to some of the user's information on the token (like its oid and email address). I'd like to be able to "extend" the token generated by the client secret to also contain a couple custom fields, which I can use after validating and parsing it.
Hopefully that's clear enough. I'm lost on how to achieve this. Thanks
It is a common requirement for APIs to authorize based on claims stored in the business data, eg roles or other custom data.
OPTION 1
Ideally the authorization server can reach out at the time of token issuance to an API or database to include the custom claims. This is not always supported though.
OPTION 2
Another option is for the API to process the incoming access token into a ClaimsPrincipal and to include custom values at that point. For an example see this code of mine.
PRIVACY
When adding more claims, you should also be careful about revealing sensitive data in JWTs returned to internet clients. Eg if you include names and emails, they are easily readable, and this can sometimes be a security concern.

I was wondering where best to store user details in reactjs aside local storage?

I am using my building journey to learn web development. I'm using nodejs, reactjs, mongodb, axios and expressjs.
Currently, I'm storing basic user details such username, id, role,email in the local storage. I could store other things as I continue.
However, along the line, I felt that storing something like role in the localstorage could be problematic since anyone can edit their localstorage. This means, user can easily edit their local storage and change their role to admin to have access to what admin has access to.
I decided to visit some known websites like Upwork, etc, I checked my localstorage and I noticed that they didn't store information such as username, email, role, etc.
As someone new in this field, where do you think is best to store information such as the above I mentioned, especially data that can grant access and change access privileges of any user? I don't think localstorage is best for this at all.
Also, while inspecting the browser developer tool, I noticed that whatever one passed from the response from backend is also seen under the response section in the web developer tool.
Is that response section accessible by Javascript? Or it is already encrypted by expressjs?
There are two concepts here which are important to understand: Authentication and Authorization.
Authentication is the process by which the server will validate that the user says who they say they are. The most common example of authentication is username and password.
Authorization is the process by which the server will validate the user can perform the action they want to perform. Once the user is authenticated, they will usually look up the user in a database and see if the user as the rights to do this (in your example, once such right could be admin).
For your example application, you could probably do something simple like store the username, a hash of the password and the user role in a table in your database. That would probably be good enough for your learning. When a user is trying to access something, look up the role in the table and if they don't have permissions to, return a 403 Forbidden
But you are just scratching the surface of the topic. For example, you said that applications do not store roles on the client side, but interestingly if you're using something like Json Web Tokens, this information will be on the client-side. In this flow, you authenticate to your service, you get a token that contains your role (admin in your example) and a signature. The signature is used to validate that the token was emitted by the service, meaning that the role it contains can be relied on. So when your application makes a request to your service, your service will only need to validate the signature.
I was once in your shoes, trying to figure out what to use when, when working with the same tech stack as yours. Let me tell you now what I use-
Decide what do I want(if it is a small application that needs to be built rapidly with all functionality I use sessions ( nodejs provides an excellent library known as express-sessions ), if I want a detailed fast app, I use JWT.
When you want to store things user settings of volume, light-mode dark mode, you can use simple local data storage.
If you are receiving data on the frontend side and want to use it there, you can use state-management frameworks like zustand, redux, or any others.
Further detail on the question -> you can modify what you store in the session like username, email-id, and all that, and as more data is needed you can request from the database once the user is verified.
If you have more specific questions to ask, feel free to fire on me, I will try my best.
Upvote if it gave you some insight on topic.
Never store important information on localstorage. Your intuition of it can be changed or it can be accessed by someone else is correct. And even if you store some data (such as jwt tokens) never trust your front end and validate it with the backend server for data retrieval.
In your case you can use session storage or cache storage depending on how to store the data that you need

how to secure azure mobile service / html - javascript

When I call an oauth provider like gmail and I get the token back, how can I make sure that all future calls I make are from that same client that did the authentication? that is, is there some kind of security token I should pass pack? Do I pass that token back everytime?
For example, if I have a simple data table used for a guest book with first,last,birthdate,id. How can I make sure that the user who "owns" that record is the only one who can update it. Also, how can I make sure that the only person who can see their own birthday is the person who auth'd in.
sorry for the confusing question, I'm having trouble understanding how azure mobile services (form an html client) is going to be secure in any way.
I recently tried to figure this out as well, and here's how I understand it (with maybe a little too much detail), using the canonical ToDoList application with server authentication enabled for Google:
When you outsource authentication to Google in this case, you're doing a standard OAuth 2.0 authorization code grant flow. You register your app with Google, get a client ID and secret, which you then register with AMS for your app. Fast forwarding to when you click "log in" on your HTML ToDoList app: AMS requests an authorization code on your app's behalf by providing info about it (client ID and secret), which ultimately results in a account chooser/login screen for Google. After you select the account and log in successfully, Google redirects to your AMS app's URL with the authorization code appended as a query string parameter. AMS then redeems this authorization code for an access token from Google on your application's behalf, creates a new user object (shown below), and returns this to your app:
"userId":"Google:11223344556677889900"
"authenticationToken":"eyJhbGciOiJb ... GjNzw"
These properties are returned after the Login function is called, wrapped in a User object. The authenticationToken can be used to make authenticated calls to AMS by appending it in the X-ZUMO-AUTH header of the request, at least until it expires.
In terms of security, all of the above happens under HTTPS, the token applies only to the currently signed-in user, and the token expires at a predetermined time (I don't know how long).
Addressing your theoretical example, if your table's permissions has been configured to only allow authenticated users, you can further lock things down by writing logic to store and check the userId property when displaying a birthday. See the reference docs for the User object for more info.

How to authenticate requests using ServiceStack, own user repository, and device ids?

I'm building a mobile app and a ServiceStack web service back-end. The Authentication stuff in ServiceStack looks great but easy to get lost in its flexibility - guidance much appreciated. I'll be using my own db tables for storing users etc within the web service. I'd like to have a registration process and subsequent authentication something like this:
the user initially provides just an email address, my web service then emails a registration key to the user
the user enters the key. The app sends to the web service for registration: email, key & a unique device identifier.
the web service verifies the key and stores the email & device id. It responds back with an auth token that the app will use for later authentication.
Then subsequent web service requests would provide the device id and auth token (or a hash created with it). The app is not very chatty so I'm tempted to send the authentication details on each web request.
Question 1: Should I hook into ServiceStack's registration API or just add a couple of custom web service calls? e.g. without using ServiceStack's registration I would:
post to a registration web service with the email address and device id. My web service would send the registration email with a key and add a record to the user db table.
when the user enters the key it would again post to the registration web service, this time also with the key. My web service would validate the key and update the user table marking the user as registered, creating and recording the auth token & returning it to the caller
subsequent requests would be sent using http basic auth with the device id as username and the auth token as password. The service is not very chatty so creds will be sent with each request.
I'll implement a CredentialsAuthProvider that'll get the creds with httpRequest.GetBasicAuthUserAndPassword() and validate them against the db data.
But it feels like I should use registration built in to ServiceStack.
Question 2: What's wrong with passing the authentication details with each request? This would make it easier for composing my app requests but it doesn't seem 'done' based on the ServiceStack examples. Presumably that's because it's inefficient if you have lots of requests to need to re-authenticate every call - any other reasons? My app will only make a single web request at most every few minutes so it seems simpler to avoid having sessions and just re-auth each request.
Question 3: Am I on the right track subclassing CredentialsAuthProvider?
Question 4: Is there any point using the auth token to generate a hash instead of sending the auth token each time? All communication will be over https.
Answer1: It will be OK. if you give multiple call as per requirement. Normally authentication works based on cookie, now you can store it on client and/or on server and match the user with it. Again here if you are using device you, can always use device instead of user to map and authenticate user. Based on your requirement.
I will prefer to use provider as it hides many details which you need to do manually instead. You are on right track. There are many blogs specifically for authentication and how to create custom authentication with service stack. If you like let me know I have book marked some will give it you. Best way to search latest one is checkout twitter account of Servicestack.
Answer2: This is again, I say as per requirement. Now if your user will be in WIFI zone only. (Mostly true for business users), then there is not limit for calls. Just give a API call and do the authentication in background. Simple JSON token will not hurt, It is few bytes only. But again if you have big user base who is not using good internet connection then it will be better to store authentication detail on device and check against that. Just to save a network call. In any case network call is resource heavy.
Answer3: Yes you are on a right track. Still check out blog entries for more details. I don't remember the code snippet and how it works with last update so I am not putting up code here.
Answer4: This is answer is little complicated. Passing data over https and saving user from Identity fraud is little different thing. Now, if you are not generating auth token (hash based value) then you can pass user also over the http or https. Now, this can be used by another user to mock first user and send data. Even data is being passed through https but still data is getting mocked. Hashed based value is used to avoid this situation. And also there are couple of other business use cases can be covered using auth token.
Please let me know if I have understand you questions correctly and answered them?? or If any further details is required??

What is token-based authentication?

I want to understand what token-based authentication means. I searched the internet but couldn't find anything understandable.
I think it's well explained here -- quoting just the key sentences of the long article:
The general concept behind a
token-based authentication system is
simple. Allow users to enter their
username and password in order to
obtain a token which allows them to
fetch a specific resource - without
using their username and password.
Once their token has been obtained,
the user can offer the token - which
offers access to a specific resource
for a time period - to the remote
site.
In other words: add one level of indirection for authentication -- instead of having to authenticate with username and password for each protected resource, the user authenticates that way once (within a session of limited duration), obtains a time-limited token in return, and uses that token for further authentication during the session.
Advantages are many -- e.g., the user could pass the token, once they've obtained it, on to some other automated system which they're willing to trust for a limited time and a limited set of resources, but would not be willing to trust with their username and password (i.e., with every resource they're allowed to access, forevermore or at least until they change their password).
If anything is still unclear, please edit your question to clarify WHAT isn't 100% clear to you, and I'm sure we can help you further.
From Auth0.com
Token-Based Authentication, relies on a signed token that is sent to
the server on each request.
What are the benefits of using a token-based approach?
Cross-domain / CORS: cookies + CORS don't play well across different domains. A token-based approach allows you to make AJAX
calls to any server, on any domain because you use an HTTP header
to transmit the user information.
Stateless (a.k.a. Server side scalability): there is no need to keep a session store, the token is a self-contained entity that conveys all the user information. The rest of the state lives in cookies or local storage on the client side.
CDN: you can serve all the assets of your app from a CDN (e.g. javascript, HTML, images, etc.), and your server side is just the API.
Decoupling: you are not tied to any particular authentication scheme. The token might be generated anywhere, hence your API can
be called from anywhere with a single way of authenticating those
calls.
Mobile ready: when you start working on a native platform (iOS, Android, Windows 8, etc.) cookies are not ideal when consuming a
token-based approach simplifies this a lot.
CSRF: since you are not relying on cookies, you don't need to protect against cross site requests (e.g. it would not be possible to
sib your site, generate a POST request and re-use the existing authentication cookie because there will be none).
Performance: we are not presenting any hard perf benchmarks here, but a network roundtrip (e.g. finding a session on database)
is likely to take more time than calculating an HMACSHA256 to
validate a token and parsing its contents.
A token is a piece of data which only Server X could possibly have created, and which contains enough data to identify a particular user.
You might present your login information and ask Server X for a token; and then you might present your token and ask Server X to perform some user-specific action.
Tokens are created using various combinations of various techniques from the field of cryptography as well as with input from the wider field of security research. If you decide to go and create your own token system, you had best be really smart.
A token is a piece of data created by server, and contains information to identify a particular user and token validity. The token will contain the user's information, as well as a special token code that user can pass to the server with every method that supports authentication, instead of passing a username and password directly.
Token-based authentication is a security technique that authenticates the users who attempt to log in to a server, a network, or some other secure system, using a security token provided by the server.
An authentication is successful if a user can prove to a server that he or she is a valid user by passing a security token. The service validates the security token and processes the user request.
After the token is validated by the service, it is used to establish security context for the client, so the service can make authorization decisions or audit activity for successive user requests.
Source (Web Archive)
Token Based (Security / Authentication)
This means that in order for us to prove that we’ve access we first have to receive the token. In a real-life scenario, the token could be an access card to the building, it could be the key to the lock to your house. In order for you to retrieve a key card for your office or the key to your home, you first need to prove who you are and that you in fact do have access to that token. It could be something as simple as showing someone your ID or giving them a secret password. So imagine I need to get access to my office. I go down to the security office, I show them my ID, and they give me this token, which lets me into the building. Now I have unrestricted access to do whatever I want inside the building, as long as I have my token with me.
What’s the benefit of token-based security?
If we think back on the insecure API, what we had to do in that case was that we had to provide our password for everything that we wanted to do.
Imagine that every time we enter a door in our office, we have to give everyone sitting next to the door our password. Now that would be pretty bad because that means that anyone inside our office could take our password and impersonate us, and that’s pretty bad. Instead, what we do is that we retrieve the token, of course together with the password, but we retrieve that from one person. And then we can use this token wherever we want inside the building. Of course, if we lose the token, we have the same problem as if someone else knew our password, but that leads us to things like how do we make sure that if we lose the token, we can revoke the access, and maybe the token shouldn’t live for longer than 24 hours, so the next day that we come to the office, we need to show our ID again. But still, there’s just one person that we show the ID to, and that’s the security guard sitting where we retrieve the tokens.
The question is old and the technology has advanced, here is the current state:
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for passing claims between parties in web application environment. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context.
https://en.wikipedia.org/wiki/JSON_Web_Token
It's just hash which is associated with user in database or some other way. That token can be used to authenticate and then authorize a user access related contents of the application. To retrieve this token on client side login is required. After first time login you need to save retrieved token not any other data like session, session id because here everything is token to access other resources of application.
Token is used to assure the authenticity of the user.
UPDATES:
In current time, We have more advanced token based technology called JWT (Json Web Token). This technology helps to use same token in multiple systems and we call it single sign-on.
Basically JSON Based Token contains information about user details and token expiry details. So that information can be used to further authenticate or reject the request if token is invalid or expired based on details.
When you register for a new website, often you are sent an email to activate your account. That email typically contains a link to click on. Part of that link, contains a token, the server knows about this token and can associate it with your account. The token would usually have an expiry date associated with it, so you may only have an hour to click on the link and activate your account. None of this would be possible with cookies or session variables, since its unknown what device or browser the customer is using to check emails.

Resources