So REST architecture implements GET, POST, PUT and DELETE requests. I would like to talk about GET requests. http://example.com/api/students this is a GET request under the REST architecture that will give me a list of students in the database.
My question is about authentication. it seems the best way to authenticate on a GET request would be by using an Access Token, like http://example.com/api/students?token=randomstring
How is this handled serverside, I mean a secuencial process, to prevent somebody from stealing another user's access token and using it. Is the token refreshed on every request and returned along the results or something like that?
First of all - you should never put credentials (access tokens) in URLs. Its not exactly wrong or prohibited per se - its just bad practice since it makes it impossible to share URLs without exposing secret credentials (think about what would happen if you copied the URL into an e-mail and send it to a friend). Credentials in URLs simply makes it too easy to accidentally expose them to others.
Take the token and stuff it into the HTTP Authorization header instead - that's why we have it. There are many different ways to use that header, but in your case you would want to use the "bearer" token method. Here is an example from the RFC (https://www.rfc-editor.org/rfc/rfc6750):
GET /api/students HTTP/1.1
Host: example.com
Authorization: Bearer rAndomSTRiNg
On the server you check the validity of the token before doing anything else. To prevent others from stealing it you enforce SSL/TLS on the connection.
The token may need to be refreshed - but that depends on how you obtained it and the rest of your infrastructure. Usually you do not need to refresh it for every request - only after a certain time when it is expired.
You may want to look at OAuth2 which defines four basic ways of obtaining access tokens.
Related
I'm currently working on a new REST Web Service, developed in Django REST Framework, and while defining URLs I had a doubt about it's security. Following the standards that defined GET method for list data from a database, I doesn't understand if this can be a safe method to bring data.
Imagine this situation:
I access an URL /patients defined to return a list of patients. This list is not public and can only be requested by authorized users. Since not all users can see all patients, I create an hash code that works as key, allowing to list patients for that specific user. If no hash code provide, the method returns an 403 forbiden.
It work something like this: /patients/HASHCODE
Since my hash code is request in the URL and not inside of the body of HTTP message, like it would be if done by POST method, this looks unsafe me. I know that SSL can hide some information of requests, but not about a GET request. And of course this hash should not be visible for no one.
Can I say this is a safe method to access my API? If not, how should I implement this?
First of all, you must use HTTPS, as it ensures that both body and headers will be encrypted. Pick a certificate issued by a certification authority and stay away from self-signed certificates.
If what you call hash means an access token, then it belongs to the Authorization header with the Bearer authentication scheme (refer to this answer for details). Alternatively, you may want to use a cookie with both HttpOnly and Secure flags set.
I also advise you to look into some sort of authorization mechanism for your application: according to the user roles or authorities, retrieve the data they can access or refuse the request. It's very likely your web framework already provides you some sort for authorization mechanism. Let me also highlight that you should't write your own security-related stuff (unless you really know what your are doing).
Any sort of sensitive information (such as credentials, access tokens, you name it) must never ever be sent in the URL: The requested URL may be logged by servers and proxies; If the URL is requested by a browser, the URL goes to the browser history. You surely want to avoid that.
GET is meant for data retrieval while POST is kinda a catch all verb, that is, the representation sent in the payload will be processed according to the resource's own specific semantics). If you need to send sensitive information to the server, I would advise you to use POST, sending any sensitive data in payload which will be encrypted over HTTPS.
I understand that OAuth2 is a good way to secure access to a REST API. I also understand that unlike in a simple website or in a SOAP API, in a REST API you want to use the right HTTP method for the right task. That is GET to read data, POST to write, etc.
My question is, when doing a GET call to a REST API secured via OAuth2, how do you protect your access token ? I don't see any other way to pass it to the server than in clear view in the URL, so isn't it that anybody that can see my call on the network could hijack my authorization ?
A HTTP request has a couple of major components:
The method
The url
Headers
Body
The OAuth2 Bearer token is usually sent in the headers, as such:
GET /thingy HTTP/1.1
Host: api.example.org
Authorization: Bearer [secret]
As an aside, this assumption is not really correct either:
so isn't it that anybody that can see my call on the network could hijack my authorization ?
If you don't use HTTPS, anyone can still see this token even if it's in a header. If you do use HTTPS, putting a token in the url shouldn't allow anyone else to snoop. However, putting secrets in urls is considered a bad practice for different reasons. Specifically, people don't like it because the tokens can end up in a browsers history and in logs. This increases the chances of it accidentally falling in the wrong hands.
Folks,
What is a simplest way to track consumer applications accessing RESTful API services inside department.
We do not restrict access - no authentication/authorization - open for invocation, trusted environment.
No tools like OAuth AuthZ servers or API management yet... but might be heading there at some point.
For now we thought to request consumers just to include some custom HTTP Header like X-Client-Id and log it on the server side for stats etc..
But knowing that in the future we might want to switch to more standard ways of doing things ... what would be best alternative to have to change less code in the future ?
Have the "clientId" in the Authorization: OAuth token (like access token)
Have JWT token in the Authorization header (looks too much - signing,base 64 etc for simple client id tracking ...)
Any ideas would be appreciated
We recently implemented this for one of our REST platforms and we used a combination of BOTH the points you mentioned, meaning Authorization header & JWT token. Although, JWT is ONLY for authentication and GETTING an access_token (oauth token) which is later used with calling actual resource apis. I will discuss how we handled this situation and you can decide on how you want to implement it.
1) Authentication
Client sends a JWT to your authentication service (/api/oauth2/auth). (If you want more reading on JWT, you can read here and here of how JWT is implemented by google and how you can use spring-security-jwt libary to handle all the signing and encrypting/decrypting). You get the "clientId" out of JWT after decrypting and verifying the signature and after server does all the authentication, you respond back with a 'refresh_token' and an 'access_token'. Server will save the access_token as well and map it to the clientId so that when client makes requests using access_token, you can know which client is making the request. The access_token expires in some time (ideally in an hour) and when it expires, the client uses the 'refresh_token' to get a new access token by posting refresh_token to some refresh token url (/api/oauth2/auth/token)
2) Authorization
Client takes the 'access_token' and uses the access token to make all the subsequent requests on all other apis (/api/*). Ideally, the access_token is sent as a part of the "Authorization" header. Server uses request filters (if you are using JAX-RS, you can use something like ContainerFilterRequest to add filters to specific url patterns and intercept them) to filter EACH request and parse out the Authorization header value. You will get the access_token from the header and from the access_token you can get the clientId that you mapped in step 1). You can do other authorization logic in the security filter and if everything goes through, you can use this information to LOG that clientId and the request that the client made.
This way you can kill 2 birds with one stone : Implement a security layer & log the information about customers (what calls they are making, how many time etc. etc.). In case you don't want to implement security filter just yet (as you mentioned it might be in the future), for now, the clients can just pass on the "clientId" (base64encoded or not, upto you) as a part of "Authorization" header. If all the calls are from a "trusted" network, it should be ok, although not as secure. This way, when you ACTUALLY implement a JWT and Oauth based security layer, all you have to do is change your ContainerFilterRequest logic to parse out access_token instead of client id (as mentioned in step # 2).
I hope this helps ! For more information on security filters you can have a look at this answer: Basic Authentication of a resource in Dropwizard. It says dropwizard, but it mostly talks about JAX-RS.
To implement full AuthN/AuthZ layer for consumer tracking would be an overkill for now.
We thought to use either to Authorzation header to pass custom client_id token:
Authorization: Custom <Client_Id>
or to use some limited version of JWT (no signatures as there no intent to validate them)
as access token
Authorization: JWT <JWT>
Where JWT could be:
{"alg":"none","typ":"JWT"}
{
"iss":"Client_ID",
"aud": REST Service URI,
"iat":1328550785
}
I do not see description of access_token format in the specification https://datatracker.ietf.org/doc/html/rfc6749#section-1.4
Are there any contraints to use JWT as access token?
I just touch with RESTful API. Basically, no matter what the rest api is, the first step is to get access token. However, I have been in two different situations:
Have client_ID, Client_secret, and username, password.
POST: api.XX.com/1/authorize?
Authorization:Basic [client_id:client_secret] must be base 64 encoded
Content-Type: application/json
Then, I get access token without timeout.
Have app_key
GET https://api.XX.com/authorize?
response_type=Pin&
client_id=APP_KEY&
scope=SCOPE
After get Pin, register in web application. Then use code to request access token.
POST https://api.XX.com/token?
grant_type=Pin&
code=AUTHORIZATION_TOKEN&
client_id=APP_KEY
Finally, I have access token and reflesh token. access token will be timeout after 1hr.
So I need to use refresh token application access again.
I just want to say, Even the RESTful doesn't have Standard, access token application methods are big different. I think the first one is better. The first one makes things simple.
Because I just start to call RESTful Web Services, I would ask:
Are these two authorization methods common way? Is there a third method to get access token? Any comments please. Thanks.
I'm designing an API for a mobile app, and I hope to keep it RESTful.
API's are authorized using Basic HTTP Auth, however, When the user open the app for the first time, he need to login first, so I need to design an API to check for user's credentials, which will accept a pair of username and password, return success or fail accordingly.
the problem is what the url should be so it is restful? I don't think /login is a good one.
It's typically viewed as poor practice to pass sensitive data via an HTTP GET request.
Password information is sensitive data and is one of the exceptions that breaks the rule that idempotent operations should be GET requests.
Why is this an exception? Browser History and Server Logs will store GET requests. Meaning that this sensitive information is visible as plain text in both places. So if someone gets a hold of either - then that information is now in their hands.
You should use an HTTP POST request to pass this sensitive information to the RESTful API as browsers will not store them and servers will not log them. However, the first line of defense is to use Secure HTTP (HTTPS) to ensure that this information is protected from outsiders.
So pass this information in the body of an HTTP request to an HTTPS URL.
A good approach is to perform a GET request for the account/profile info of the current user. and have it return the username, settings, avatar url, etc. me is a frequently used as a shorthand identifier of the authenticating user.
GET https://api.example.com/profiles/me
HTTP/1.1 200 OK
{
"username": "bob",
"id": "xyz",
"created_at": 123,
"image_url": "https://example.com/bob.png"
}
From wikipedia:
The client–server communication is further constrained by no client
context being stored on the server between requests. Each request from
any client contains all of the information necessary to service the
request, and any session state is held in the client.
Because the server stores no session state from the client, your API shouldn't expose any login/logout capability: In each request you should send user credentials, and the server should validate them each time.
Check this discussion in SO, it claryfies this concept.
I agree with Carlos - in a normal restful API, there is no session so you can't authenticate once and then reuse the session, you would actually need to pass the credential set on every call (not ideal).
In this scenario it sounds like you would be better of using one of the openAuth (http://www.oAuth.net) - this works by authenticating when the app is first run and then generating an access token to allow access within every call (+a refresh token).
(you could argue that the access token is state - which it kind of is - however, at least it's generally significantly longer lived).
GET https://api.example.com/auth
With Authorization header set.