Can I send access token using GET method? - rest

I'm building RESTful API, but I have some question while implementing /valid
endpoint.
/valid endpoint checks token expiration.
Is GET method good choice for this endpoint?
Is there any problem with sending token using GET method?
(like http://some.api/valid?access_token=ACCESS.TOKEN.STRING )

If you use GET, your server log will be full of access tokens. This may be a security issue to consider.
What you're doing is essentially RPC, passing a parameter (access token) into a function (validate).
To do it using REST, you could consider the resource as the access token. As you have it, it's already been created (POST) so you would want to interact with it in some way. PUT updates a resource but you're not updating but you're not using REST either so it doesn't really matter. You could use POST but as I said, the resource (access token) has already been created.
So to get as close as possible to REST, you could:
PUT /accesstoken/validate
body: ACCESS.TOKEN.STRING
and get a suitable response. It also allows the server to track whether the access token has ever been validated, if that's of relevance. As it's RPC, it means the server could do other things that may update the resource in some way. i.e. number of times it's been validated and the ip address it was validated from, increasing security perhaps.

Related

What should be REST response for GET call with identifiers as the query parameter if user does not have access to some of the requested resources?

I am designing a REST API, where the user can place a GET call and fetch a list of items.
One of the query parameters that this API is allowing is also ids, a comma-separated list of identifiers that should be fetched.
This is an ability to filter items based on the known ids of resources.
GET /entities?ids=1,2,3
Now, there is also an authorization framework in this mix that provides an answer of what resources the user actually has access to.
So, say from the list of requested ids: 1,2,3 the user has access only to 1 and 3.
They are not allowed to access a resource with id 2.
What should be the REST response in this case?
Should I ignore the fact the user is asking for the forbidden resource and return 200 with the body containing items with ids 1 and 3?
Or, maybe, return 403 in this case... Opinions?
This request should fail
The client is explicitly requesting a specific resource that it doesn't have access to. That should not be part of the normal flow of your application, and I'd say it warrants an outright rejection.
The client may need to process the returned data, so a successful response that doesn't include the requested data should not be allowed to happen. If you do it, your client needs to write more code to account for this outcome, raising the likelihood of bugs and breaking trust with the client. Just return an error instead. Your client needs to handle these in any case.
My choice would be a 403 response with a message that informs the client why the request failed and includes steps to correct the issue.

Which REST HTTP verb to use for "Q&A" scenario?

An auth system I work on has this new function:
1. Auth system allows users to specify Relying Parties they transact with,
2. The Relying Party can approve/deny/maybe the request (authorisation) - maybe causes a redirect to the RP website for further authorisation questions by the RP.
The RP has to implement a web service specified by the Auth System to perform the approve/deny/maybe request that the auth system generates.
My problem is what this looks like as a REST service. As the auth system can't really dictate the URI style for the RP system, i would like to specifying that the path does not have any parameters in it, auth system just needs to know the URI of the service. The data of the request (user name/id) might be in a bit of json in the request body (suggesting POST http verb. GET might be OK, but loath to expose user ids in the URI). The auth system does not care what the RP does with the request data, the auth system just wants a "yes/no/maybe" reply (so may not really be a GET/POST/PATCH/DELETE/etc paradigm).
What would be the best verb to use? and how to facilitate the reply; its not really a success/failure response as there are 3 possible results to the query, is it acceptable to have some json returned with the response (then what http verb to use)?
I'm a bit baffled by this. GET seems the most obvious
GET /api/user_link_authorize/{userid}
except then i'm forced to put user ids in the URI (which I dont want to do)...
Any suggestions?
My problem is what this looks like as a REST service.
Think about how it would look as a web site.
You would start with some known URI in your list of bookmarks. Fetching that page would give you a representation of a form, which would have input controls that describe what data needs to be provided (and possibly includes default values). The client provides the data it knows about, and submits the form. The data in the form is used to create a HTTP request as described by HTML's form processing rules. The response to that request includes a representation of the answer, or possibly the next bit of work to be done.
That's REST.
Retrieving the form (via the bookmarked URI) would be a GET of course; we're just updating our locally cached copy of the forms "current" representation. Submitting the form could be a GET or a POST; we don't necessarily need to know that in advance, because that information is carried in the representation of the form itself.
GET vs POST involves a number of trade offs. Semantically, GET is safe, it implies that the resource can be fetched at any time, that spiders can crawl it, that accessing the resource in that way is "free". Which is great when the resource is free, because clients on an unreliable network can automatically retry the request if the response is lost. On the other hand, announcing to the world that the request is safe when it is actually expensive to produce responses is not a winning play.
Furthermore, GET doesn't support a message body (more precisely, the payload has no defined semantics). That means that information provided by the client needs to be part of the target resource identifier itself. If you are dealing with sensitive information, that can be problematic -- not necessarily in transit (you can use a secured socket), but certainly in making sure that the URI with sensitive information is not logged where the sensitive data can leak.
POST supports including a payload with the request, but it doesn't promise that the query is safe, which means that generic components won't know if they can automatically retry the request when a response is lost.
Given that you don't want the user id in the URI, that's a point against GET, and therefore in favor of POST.

REST : Correct HTTP verb to check a password

I read many posts about passing sensible data in a GET request but didn't find an answer that would suit my needs.
I have to expose a RESTful resource that will check the password strength.
GET http://api.domain.com/security/password/P#55w0rd
I find the GET HTTP verb suitable since I only want if the password is secure enough.
The problem is that the client will be forced to pass it in the resource (i.e. URL).
Some colleagues told me to use POST and then pass it in the data body but I'm not sure how RESTful is it.
The REST standard just says to use HTTP Verbs. It doesn't actually mandate that you use particular ones. However some conventions have arisen about which verb to use, POST to create & GET to retrieve data, however this should not be followed religiously if it will cause an issue.
As per the following article you should not use GET for password, and yes you can use POST or pass something in the HTTP headers instead.
REST Security Cheat Sheet
Session management
RESTful web services should use session-based authentication, either by establishing a session token via a POST or by using an API key as a POST body argument or as a cookie. Usernames, passwords, session tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them intrinsically valuable.
I went with this:
GET /api/public/check-password
Authorization: Basic <base64(test:<password>)>
The username must literally be either '' (empty string) or 'test'.
I chose to use
test because it's obviously not a real user
GET because no modifications are made
The Authorization header because the security middleware in (most?) application stacks already removes that from logging - so no special care is needed.
/api/public because it doesn't require authentication to do the check
I'm not in love with check-password - that sounds more RPC-ish than REST-ish... but what can you do? At least it's obvious. I'm open to other suggestions.

Is leaving out the current user ID in a REST endpoint bad practice?

I'm currently writing my own REST API. One of my endpoints is named /api/profile, which takes either GET to retrieve or PUT to update this profile. I have been told that it's considered bad practice or plain wrong to not include any form of user ID, email or username in the URL, when calling PUT /api/profile. Every request has a Bearer token for authentication, which makes the server load the user in case and stores it in the request data. Upon updating information using PUT, I thought it'd be safe to assume that if no parameter has been supplied to the URL, the target is self, in this case, the authenticated user.
Am I wrong to make this assumption and/or is this a bad example of REST?
One of the architectural constraints of REST is to make your resources cacheable.
When you have some proxy or other cache between your client and server, the request line GET /api/profile cannot be cached, or another user would potentially retrieve the wrong profile.
You could use a Vary: Authorization header in your case to prevent this. But having an id in the URL will make unequivocally clear which resource you want to retrieve.
For PUT requests, this is not an issue as they won't be cached, but you should keep your URI design consistent.

Client Facing REST API Authentication

I have seen many different posts regarding different solutions for authenticating a RESTful API and I have some questions, given this current scenario.
I've built a REST API that will allow clients of my software service (we are a B2B company) to access resources programmatically. Now that I've got the API working properly, I'd like to secure it in the most standardized way possible. I need to allow access to certain resources based on the caller of the API. That is to say, not all users of the API can access all resources.
I have URLS available in the following formats:
https://mydomain/api/students
https://mydomain/api/students/s123
https://mydomain/api/students/s123/classes
https://mydomain/api/students/s123/classes/c456
So far I've come up with these possible solutions:
Provide a unique key to each client that they can use to ultimately generate an encrypted token that will be passed as a GET parameter at the end of each REST call to (re)-authenticate every single request. Is this approach too expensive
https://mydomain.com/api/students/s123?token=abc123
Provide a value in the HTTP Authorization Header as seen here. Is this almost the same as #1? (Except I can't paste a URL into the browser) Do people use these headers anymore?
Use OAuth 2 (which I'm still a bit unclear on). Does OAuth 2 actually authenticate the client as a logged in user? And doesn't that go against the spirit of a REST API being stateless? I was hoping OAuth was the proper solution for me (since it's a public standard), but after reading up on it a little bit, I'm not so sure. Is it overkill and/or improper for REST API calls?
My goal is to provide an API that will not have to be changed for each client that wants to consume the API, but rather that I can provide a standard documentation made available to all of our clients.
I'll be happy to post additional details if I've been unclear.
There are 2 type of clients you probably want to prepare your API:
trusted clients - Which are written by you. They can have the username and password of the actual user, and they can send that data to your server with every request, possibly in a HTTP auth header. All you need is an encrypted connection by them.
3rd party clients - Which are written by some random developer. You can register them in your service and add a unique API key to each of them. After that if an user wants to use their services, you have to show her a prompt in which she can allow access to the 3rd party client. After that the 3rd party client will be assigned to the user's account with the given permissions and it will get an user specific access token. So when the client sends its API key and the user specific token along with the request, then it sends the requests in the name of the user.
OAuth can help you to control the second situation.
Your URLs do not have a meaning to the clients. By REST you have to decouple the clients from the URL structure by sending links annotated with semantics (e.g. link relations). So your documentation does not have to contain anything about the URL structure (maybe it can be useful for server side debug, but nothing more). You have to talk about different types of links. By generating these links on server side, you can check the permissions of the actual user (or 3rd party client) and skip the links which she does not have permission to follow.