REST API design - querying mail data - which poison to choose? [closed] - api

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
we are currently designing an internal REST api. we have the following use case:
a user (109) wants to read a message that he has sent to another user (110)
the reading user (109) is known to the app through his token credentials that he received after authenticating (while doing the GET request)
we assume in this example the user 109 was the sender and 110 the receiver
to summarize from the users perspective "give me the mail that i (109) have sent to 110"
the following URIs came to our mind but we can't decide which one to take:
a) GET http://localhost:9099/api/mails/109?receiverUserId=110
b) GET http://localhost:9099/api/mails?senderUserId=109&receiverUserId=110
c) GET http://localhost:9099/api/mails?receiverUserId=110
d) GET http://localhost:9099/api/mails/me/to/110 (when logged in as 109 via token credentials we know that "me" is 109)
f) GET http://localhost:9099/api/mails/109/to/110 (explicit request, e.g. for admins … has to be guarded against illegal access)
all the links are "context sensitive" that is sending one of the links to the receiver (110) will yield different results executing the GET request.
i would like to know your opinion on what url to use.
any help highly appreciated.
cheers
marcel

Different responses to different clients, for same URL is okay.
StackExchange does it:
GET /me/comments/{toid}
which is documented here.
Twitter does it too:
GET /statuses/home_timeline
which is documented here.
Both of those URLs infer the logged in user based on authentication. Yes, it defeats caching if users share a cache, but IMO, this is okay. Whether or not this breaks the 'resource identification' constraint of REST is probably debatable. The answer to this question, and a subsequent comment there shows to me why it is debatable.
In fact, among the options, you do mention URLs which are not 'context sensitive':
GET /api/mails?senderUserId=109&receiverUserId=110
This one will always return messages from 109 to 110. But while one client would want to see this result when viewing 'sent' messages, the other would want to see this result when viewing 'received' messages. Kind of weird eh? Plus, on the server you'll have to check that the authenticated user is 109|110, else throw a 401 UNAUTHORIZED.
I would go with something like:
GET /mail/sent
returns all sent mail. And:
GET /mail/sent?to=110 (like applying a 'filter' to /mail/sent)
OR
GET /mail/sent/110 (clean URL)
returns mail sent to 110.

"Context sensitive" links are bad idea for a REST API (in particular, this hinders caching). If you want to just use HTTP this is OK.
So I would suggest using URLs that do not depend on current user and limit access to them according to your rules.

In my opinion, you need 2 layers:
One is the internal layer, which doesn't require user authentication, it's only accessible from internal components. It includes APIs like
GET http://localhost:9099/api/mails?senderUserId=109&receiverUserId=110
The advantage of this layer is the testability, reusability and cachability.
The other layer is the external layer, which requires user authentication and is accessible from external clients. It includes APIs like
GET http://localhost:9099/api/mails?receiverUserId=110.
Clients must login to get the token credentials, then server can get the user info from this token, and map the external API call to internal API call.
You may have different kinds of authentication methods, but the internal layer will not be changed, you just need to map different external layers to the internal layer.

Related

Authorization best practices? Where should authorization take place to hide/block pages from the user in nextjs? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 days ago.
Improve this question
I am currently in the process of designing a network of servers and databases for a project.
One key aspect of this project is the implementation of a central authentication server which will utilize session IDs to track sessions. These session IDs will be stored in cookies and sent back to users upon successful login.
Note: I understand that nextjs can work as both a front end and a back end. For reasons I will not get into here, nextjs is being used as a front end, and a separate central authentication server is being used for authentication. There are other servers/databases that will store data that users can access if they have proper permissions levels.
In step 1, I have no questions.
In steps 2 and 3, when the cookie is sent back to the nextjs server, what is the best practice for nextjs to determine the authorization level of the user?
I believe it's important that...
- Nextjs should know what navigation tabs to show, etc., when it renders the page for the user.
- Nextjs should also know what pages the user is allowed to visit. If the user is asking for a server-side rendered page that it isn't allowed to visit, it should be blocked
Possible option: Here, do I include some sort of JWT with authorization levels? It is my understanding that nextjs may be able to read these JWT authorization levels in middleware, then deny certain page requests that the user has by reading the JWT each time they request a page. Perhaps, even without middleware, functions could be used within the pages that would run server-sided, checking the JWT permission levels. Note that, in order for the nextjs server to know what the authentication levels are for the user, the tokens would have to be created in the central auth server, and then sent to the nextjs server.
Side thought: It seems that if I were to implement a function that checks the authorization level on a SPA, there would always be a way that a hacker could at least visit the blank page, correct? In other words, the only way to truly hide pages and navigation tabs from a hacker would be by somehow checking authorization levels server side (server-sided rendering), and then sending back a rendering of the page that only shows items related to the exact permissions of the user?
Overall, I would greatly appreciate any advice or insight on the best methods for authorizing users and limiting access to pages and tabs based on permission levels. While cookies will be used to store the session id and determine the data that users can receive when making API calls, additional measures such as JWT may be necessary for authorizing users to view specific pages. Is it common to utilize a combination of session/cookies and JWT for this purpose? What are the recommended best practices in this scenario?
Thank you for your assistance.

Building an API to send random numbers to my website [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
I am trying to make a custom API which uploads random numbers generated to my website page (to learn how API works). And whenever I want to see the page, I use my API key to do so. Can you help me in this? I am new to API stuff.
When creating APIs, there are lots of decisions to make. You could render your structure on the client-side and query your application server via RESTful API calls. Or you could have a server-side rendering approach and use your API internally. There are four main types of APIs:
Partner
Internal
Composite
REST
https://www.techtarget.com/searchapparchitecture/tip/What-are-the-types-of-APIs-and-their-differences
In your scenario it seems that you need to either choose an internal API approach or a RESTful approach.
Your random number function itself would be similar in both cases (a simple function written in the language of your choice).
However, the token usage largely depends on the type of your API.
You need to decide whether you are going to have usernames and passwords and is the purpose of your token only to avoid frequently logging in with very sensitive data, such as username and password, so, you use a token instead, which, if falls into the wrong hands, then they could not steal the identity of your users for good, as they are still not reaching these credentials. If so, then you will need to generate the token periodically. A way to do so is to generate it every week/month (whatever) and somehow send it out to your users. Or it could be generated whenever the user has to log in, sent to the user, who will be able to use that token from there on.
Or, you could separate the token from the login and provide a UI for the user where he/she can generate tokens while being logged in. There are quite many ways to approach this.
Otherwise, if there is no username and password and, there is a token and secret to identify the user, then you will need an alternative to the login. It could be a simple request for token generation. Or it could be a repeatedly generated and sent token.
In any measures, when you intend to run an API function as a user, then you will need to send the information that identifies your user. On most webpages this is handled by getting a session ID (that acts as a token) upon login and then, while the session exists, that session ID is always sent to the webpage, whatever request is being sent, this is how the website knows that you are logged in. Most webservers and programming languages that handle web requests also handle token generation and usage and browsers are in line with these through the cookies, which are small files that contain information for the website.
If you are having a custom environment or you prefer a custom token management, then of course you can implement your own.
But, if you want to achieve simplicity, then you could implement a register and a login feature for your API as well as the number randomizer, so these are 3 API functions for now, call the register when a user registers, store a 1-way-encrypted password, do a validation (like email sending with a token to the user) and implement token-based user validation, which is a fourth API function. So, the user:
registers
receives an email with a token
clicks on a link that has that token as a request parameter
once that page opens, store the user as an authenticated user and remove the registration token
This will enable logging in for your user. Once your user is logged in, a session ID should be generated (in PHP you need to look into the functions whose name start with session_, for example) and then using that session ID your API should make sure that the randomizer can be called and your UI should be designed in such a way that this feature could be found by users.
If I may, I advise you to avoid getting into your own token generation while you are learning, choose the simplest ways and once the simplistic configuration you have chosen is working reliably, then you may choose to write your own token logic if you prefer that for some reason.

How to properly secure post requests with Django RF apis?

I am currently learning to make DRF APIs for something I am working on. I was wondering how exactly I would secure the API POST requests I send via the client side?
For example, let's say I have a log in form where the user can enter their information, this information needs to be send to (or POST-ed to) my API for verification. I do not want just anyone sending requests to the server and so, I would want to use an API key but since this is being done on a website, anyone could see the API key if they wanted to, and then exploit the server by sending a ton of requests.
My current idea is to use serializes in DRF to check if the API POST request has everything it needs but I am fairly certain this can be easily found by checking what sort of JSON my code sends to the server, so how exactly do I go about securing this such that I can send the information to the bare domain (like http://127.0.0.1:8000) and then have code which can accept that information?
I apologize for any confusion, if it is confusing. Let me know if you need any clarification.
If you are creating API any one can send request to server. same goes for website and webpage. Their is no way you can avoid this. But their are ways to handle possible misuse.
like using CAPTCHA for login form which can be filled by one on the web. though wrong CAPTCHA text can be send by anyone you must check it on server for their correctness. or use google reCAPTCHA like services for outsourcing this task.
API key should be given after login NOT before login. and if it is given after successful login then the key is obtained by legitimate user which can obviously do whatever he is allowed to do on website. their should not be problem in that.
further explanation to the question will lead to details of denial-of-service i.e DOS attack. you should consult expert on that field if your application requires to handle DOS attack.

Is this a correct implementation of REST?

Im steadily building the resources of my API, however after much research on the correct ways to build a RESTful API, I have been unable to find an example of how 'complex' requests should be received.
For example, as part of the login process (which is little more than an authentication key update), the following URI is dispatched by the client:
/api/auth/login
There are no values on the URI, the resource is /auth/ and the command being triggered is /login/. The actual login details are sent to the server Authorization header.
Now, what prompted me to ask this question is as I was writing a command to allow the client to get a reminder of how long the key is valid for, I was immediately drawn to getkeyexpiration or something similar as a command name.
Suddenly I felt that this doesn't sound like what I read about in the 6 constraints, this feels more like operation calls.
So, based on the above examples, is this still a RESTful API? I am concerned as I cannot think of a way to perform this by simply using URI resource names and appended values.
Thank you
EDIT:
From reading this: http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http
I am starting to understand that by naming resources and only resources with noun words, the context of how the server will operate becomes a lot clearer.
Regarding my above example:
/api/auth/login
I have used auth as a prefix of login, because that is the context of the resource. I am designing my system to be extendible and require a way to categorize resources on the URI level. Is there a standard way of doing this?
Your RESTful resources should be nouns, because HTTP provides the verbs.
I would suggest something like this instead:
/api/key
Which you can then POST to (with HTTP Authorization headers included) create a new key, returning something like this:
/api/key/1234ABCDBLAHBLAH
This is a key specific to your session, which you can then GET to retrieve details about it such as expiration time, etc. You will have to pass that key with each subsequent request, of course.
If the key stuff sounds clunky when discussed in the context of a RESTful API, it's because it usually is. Sessions are human/browser concepts, but RESTful APIs are application/integration concepts.
Since servers don't "log on" to other servers, this begs the question: if you're already OK with requiring the caller to pass an Auth header to your login API, why not just require it be passed for each API call, and forget the notion of keys altogether?

RESTful HTTP: Showing different representations to two users on the same URI

I'm designing a hypermedia API, yes, a RESTful API, with the hypertext constraint.
Each user of the system will access the system using their own credentials, so every request we process is authenticated and authorized. Each user will typically have specific credentials so that they may have different permissione (e.g. none, read, read/write) on each collection.
We want the client to be primed with the one URI that it starts with, which would be perhaps an atom services document, or a hierarchy (draft atom hierarchy extensions) of atom collections.
My question is basically should users see different representations for the same URI, or should users be directed to different URIs based on their permissions?
For example: User A and User B have different permissions in the system. They log in with different credentials, to the same start URI. A successful response may be one of the following 2:
200 OK, and User A sees something different than user B on the same URI
302 (or other redirect) each user to e.g. /endpoint/userA (which they own)
The tradeoff between cacheability is of course minimal, since resources are cached only by the client and not by intermediaries, but there's a tradeoff for visibility too (URI contains (aythenticated) user ID). Finally there's the future possibility of allowing User A (or a super user) to see what User B sees.
I'm not asking what Twitter or Facebook do, I'm more interested in what REST practicioners have to say about this.
My question is basically should users see different representations
for the same URI, or should users be directed to different URIs based
on their permissions?
For example: User A and User B have different permissions in the
system. They log in with different credentials, to the same start URI.
A successful response may be one of the following 2:
200 OK, and User A sees something different than user B on the same
URI
302 (or other redirect) each user to e.g. /endpoint/userA (which
they own)
Both ways are RESTful. The representation of a resource can depend on the permissions. The communication is stateless because you send the credentials (username, password) with http auth by every request. Redirection to another representation variant after permission check is a great idea. That way you can completely separate the authorization logic from the resource representation logic, so you can move it even to another server and you can create very well cacheable resource representations. For example by GET /endpoint/userA you can redirect userA to /endpoint/userA?owner=true, because she is the owner of the profile, or you can create a composition of features: /endpoint/userA?feature1=true&feature2=false etc... It is very easy to setup fine grained access control for that. Another way to stay cacheable if you append the user id to every request's queryString, but this solution with redirection is much cleaner. Thank you for that!
Personally I find this a really tough call to make and I think it depends a lot how much content would change. If the difference is the omission of a few extra details then I would probably treat it as a single resource that varies based on the user.
However, once the differences start to get more significant then I would look at creating different resources. I would still try and avoid creating resources that are specific to a particular user. Maybe for a particular resource you could create a set of subresources, with differing levels of content. e.g.
/Customer/123?accesslevel=low
/Customer/123?accesslevel=medium
/Customer/123?accesslevel=high
This method in combination with the 302 may be sufficient in some cases. For more complex cases you could use multiple query string parameters.
/Employee/123?SocialSecurityNo=yes&SalaryInfo=yes
I do not believe there is an easy answer to this question. I think the answer is similar to most tricky REST scenarios: your solution can be as creative as you want as long as you don't violate the constraints :-)
Option 1, replying with 200 is an acceptable REST response and is more user friendly than option 2.
The Google Data APIs provide a decent REST implementation on top of their user services, and they implement option 1. For example the Google Calendar Data API allows a user to query the person's own feed by performing a HTTP GET request on http://www.google.com/calendar/feeds/default/private/full.