How to fetch user's data once they have a JWT - jwt

I'm using JWT's for user authentication on my e-commerce website. Once a user successfully logs in, I'm sending them a JWT which is stored in the browser's localstorage.
Once the client has the JWT, I'm trying to figure out the best (or a standardized) way for the client to fetch certain data for that user? This data includes their shopping cart, wishlist, order history, etc. I can think of a few possible solutions:
Include all data in the JWT. This is probably the wrong approach. Seems like only data such as user_id, phone_number, and email_address should be stored in a JWT (source).
Allow the client to parse a user_id (e.g. 75) from the JWT. Client then hits /users/75 (JWT required for authentication) to fetch the user's data. However, this seems redundant because both the endpoint and the JWT point to the user.
Create some endpoints like /user/shopping_cart and /user/wishlist for the client to hit (JWT required for authentication). The backend will determine which user is making the request based on the JWT. This seems like the better option.
I would bet option 3 is the best approach?

storing some info like basket items can be done either in client side or back end, as you said you can save info and fetch them by user id, but some info can like shopping cart can be stored in localstorage to, in back end fetching speed is matter, i suggest using redis for stuff like simple info in back end.

Approach 1, Storing everything in JWT:
every time user update their cart or wishlist you have to generate a new JWT and return it to user. You wouldn't want to generate a new token on every action(add/update/delete) done by the user. Although you can encode data in JWT for initial data loading.
Approach 2, return everything with a single request
This approach is good for smaller amount of data and data that are interrelated to each other. For eg in some cases, you might want to show # num of items in cart, num of wishlist items, total orders they have made on a single page. In that case, you can make something like /dashboard which returns basic information about the user.
GET: /dashobard
{
wishlists: 5,
totalOrders: 100,
cartItems: 10,
}
Approach 3
I would go with this approach. As your application grows and a large number of people are using it, they will have multiple wishlists and multiple past order history and your application might have separate pages to show that information. In that case, having a separate route for each resource is a good idea.
GET: /users/1/wishlists/ --> get all wishlist of user 1
DELETE/UPDATE: /users/1/wishlists/10/ --> update wishlist with id 10 of user 1
GET: /users/1/orders --> get all orders of user 1
You can combine all the approaches and use accordingly

Related

REST API design authenticated user: /products or /<userid>/products

I'm building a web app with VueJS as front end and authenticating user to an API with JWT.
If I want a API to display only user products (filtered), should the route be:
/api/products
and the backend do the filter
or
/api/userid/products
and restrict access to others users products
You'll have the user_id from the JWT so for us we just use /api/products in our software. We avoid having multiple sources of data as that can create confusion and anything in the JWT is authenticated so we can trust that.
If I wanted to allow a user to see products from other users, I'd use /api/products/search?user_id=XXX for a flexible search system that could be expanded to search products by other criteria.
I find it better to make the user id part of the uri. Ultimately this is subjective, but it has a few advantages:
It makes really clear that the list of product in this case is a subordinate of users. There's no doubt it's the 'entire list' if it looks like a sub-resource.
It keeps the door open in the future to allow users to access product lists of other users.
I like the idea of giving every entity in my API a completely unique URI. To me, every user in your example has a personal product list and each product list is a unique resource.

REST API Design: When should we use association in Uri for the resources?

We have simple e-commerce website where we have several products. Currently, each product has "Place order" button.
When user clicks on this button, we show user a form to fill Name, Mobile number and address. We don't support any monetary transaction. Once user fills this form, the order is saved to database. The order table has OrderId, ProductId, UserName, UserMobile.
We are designing API to save the user order. Should we have association b/w product and order while designing this?
For example URI to save the user order should be like:
POST /api/products/1/lead/ - The request body has user information i.e. name,mobile,address. OR
POST /api/lead/ - The request body has "PRODUCT ID" and user information i.e. name,mobile,address.
I am confused whether productId should be in request URI or in the request body? How do we make such decision?
Given that
you're first navigating to a product, before actually placing the order
the product id has nothing in common with the UserInformation model that you're posting
I'd go with the first option: POST /api/products/1/lead/
I would always go with a more shallow route for representing resources, just for the sake of simplicity. No, a nested route isn't complicated or anything, but I've seen nesting go really far. So I would keep it as shallow as possible unless...
1) You plan on having more than one thing that can have a lead. For example, you can have a lead on a product:
api/products/1/lead
or a lead on a managed service that you all provide or something (I'm reaching right now):
api/managed_services/2/lead
You could pass that info in the body always, but I imagine it would become a little cumbersome to base what resource to create based on what properties were defined in the json.
2) You plan on breaking out that route and having it go to a different service eventually. Maybe this app will have to scale substantially and a ton of users will be hitting this route moreso than any other endpoint in the system. It's a lot easier to redirect all requests to a different microservice based on the url starting with api/products than it would be redirect based on the request body.
But honestly, I don't think it matters too much. As long as it's easy for your clients to consume.

REST - Api design for posting a form data and fetching another resource

I am developing a feature, where a user requests some data by filling a form and posting it. The form contains user details (name, email, mobile etc.) and these details need to be saved in the database as a lead. Once the lead data is saved successfully then only the requested data will have to be retrieved from the database and shown to the user.
I started looking into this problem by dividing it into below two APIs and calling it sequentially
A POST API to create a lead resource.
A GET API to fetch the requested resource on the success of POST.
But then I realized that the solution will affect the speed of data retrieval as I will be doing two separate network request sequentially and I cannot compromise on speed.
How can I solve this problem without compromising on speed? Should I use POST request and return the requested data in its response?
P.S. I cannot call both the APIs in parallel
Yes, that's exactly what you should do - the POST request should respond with the newly created resource, that the client can subsequently use.
You have been thinking about the problem from the web developer's perspective. You have this byte stream and to send it to clients doesn't need any form submission, a GET request ought to suffice. But from the business' perspective, retrieving the file does require a form submission, namely, the user's personal data. Even from the user's perspective it is a single operation. The user sends in the requisite data in order to get out the desired response (e.g. a file download). The saving of the input data (user's private details) is a side effect, not a user-intended outcome.
As such, a single POST request which submits the user data, saves it, then responds with the requested resource, is sufficient to cover the situation.

Can I use jwt to store a user's shopping cart items until checkout?

I'm using the MEAN stack on my site, where users can add events with player information (2-4/event) to the cart. Sometimes they purchase multiple events. I'd like this information to be safe from user manipulation (changing info before checking out if they use console) and able to be stored for a short time in case they are interrupted during checkout.
Would I be able to add their cart items to their JWT, and then remove it once they checkout and the data is stored in the database or is there a better option? I saw options for local-storage or session-storage but am not sure what the best option is.
In theory there is no limit max size of JWT, but in practice, it is used to authenticate the user so supposedly the smaller the better. I think it's totally possible strategy. The advantage of using jwt would be that it doesn't have to hit the db. On the other hand, a lookup like this (normally) should be be trivial. You also should be careful that you don't leak any secrets into the jwt since it is possible to view the contents.

Is it bad practice for a REST endpoint to return different response fields based on the request?

I'm developing a 'user' endpoint for my mobile app. When the authenticated user GETs another user's profile, I want to return fewer fields than when they GET their own.
Is it semantically bad/against REST principles to return a different set of fields from a REST endpoint depending on some criteria such as whether the requesting user is retrieving their data vs another user's, or should I just have 2 endpoints for the same data source?
It's totally fine to return differing sets of data for the same URL based on authentication criteria. Think about a plain old web site. If you're logged in, you usually see diff contextual information than you do if you're anonymous, right? So getting more info back in the content of your response when it's the "current" user vs. a diff user is the same thing. If you really wanted to separate the fields you could with a sub-URL, but you definitely don't have to.