Consider OAuth-2.0 Authorization Code Grant protocol.
As described in standard draft http://tools.ietf.org/html/ietf-oauth-v2-26 on Figure 3 : Authorization Code Flow a Client is getting token on behalf of Authorization Code received from User-Agent. Suppose that User-Agent is intentionally sending wrong codes to the Client. If Authorization Server makes some protection against brute force way of obtaining Access Token by banning Client for some reasonable amount of time (by IP or by Redirection URI host name). If in our case the Client is supposed to process horde of requests from multiple different User-Agent's the Client will stop to serve all its users altogether if there's only one malicious one exists.
So the Client becomes a bottleneck in a situation described above.
==== EDITED ====
Any ideas how to evade the bottleneck problem?
I believe you're asking:
"how to evade this problem and NOT to expose Authorization Code to User-Agent?"
This is not possible. The OAuth request flows through the user's browser so you can't prevent exposing the authorization code to the user.
If you're a victim to an attack like this, I'd suggest putting the same protection into your Client that the OAuth provider is putting into their Authorization Server. Namely, stop allowing new authorization codes to be sent from a User-Agent that's abusing your service. If they send more than, say, 3 invalid tokens per hour, ban them for an hour or two (by IP address). Of course, this could lead to you denying access to your site from proxy servers because of one bad user on the proxy, but that's life.
Related
I am building a web application and my web server is secure, meaning that it uses an ssl cert with the front end to encrypt the connection.
When a user logs in, a JSON object which looks like this is created, and sent to the server.
{
username:"the user's username",
password:"the user's password"
}
On the server this is verified with a hashing algorithm that uses a salt. Once it is verified an api token is created which is valid for a certain amount of time, and is passed back and forth in the header in order to verify the user when requests are being made. Is sending the username and password like this best practice/secure, or is it better to send it in the header?
Lets divide it to many points:
1) you use a valid SSL certificate to secure the communication between the user and the server (It must be valid)
2) Sending the username and password in the body of the POST request is the best practice (Never use GET to send sensitive information such as Credentials)
3) Sending the api token in the HTTP request and response headers is the best practice (Again never use GET to send sensitive information such as session tokens)
So based on the points above, it seems that there is no risk in this implementation but you need to take the following points in your consideration:
1) The time out of the API token should be short in case of idle user. (5 ~ 15 mins are the averages based on the criticality of the application)
2) The length of the API token should be long string approx. 30 ~ 40 characters.
3) The API token generation must be randomized and hard to predict to protect from (session prediction attacks.)
Hope this help you.
What you are describing is basically HTTP basic authentication.
Is sending the username and password like this best practice/secure, or is it better to send it in the header?
In security point of view I cannot think of a big difference whether you send the credentials in the body or in the header. Basically whoever manages to read the clear text message, can see the credentials in both components. The common practice when using the basic authentication is to use the HTTP header though:
Authorization: Basic VGVzdFVzZXI6UGFzc3dvcmQxMjM0
where VGVzdFVzZXI6UGFzc3dvcmQxMjM0 is your base64-encoded credentials. The decoded string in this case is: TestUser:Password1234
It is important to realize that in your case the TLS is the only protection for the credentials in transit so you must identify all the nodes in the communication channel that could potentially expose the clear message. For example if you are using proxies that would terminate the TLS, those proxies are potential vectors for MITM attacks.
If you want to increase the security for the credentials in transit, one option could be to implement asymmetric end-to-end encryption so that you would encrypt the credentials with an authenticated public key on the client-side (e.g. certificate signed by a trusted CA) and then decrypt it at the destination with the private key known only for your server. In this case you would not need to worry too much what happens to the message in-transit.
I've built a stateless, JWT-based user authentication system on my web server, following the example of Stormpath (https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage).
The setup seems pretty secure against CSRF, but I'm wondering what about the GET requests.
I was able to model a CSRF attack on GET request by including an <img> tag on a page from a different domain. The server responds to the request with a full page with 200 status. While I don't change any data on GET requests, the pages may still contain some sensitive information, for example, <img src="https://example.com/account" /> may give out user's details, and or <img src="https://example.com/logout" /> could simply do something annoying, and I think there can be more examples.
Is this <img> attack considered harmless, because the browser will not disclose the repsonse it gets? Are there any other tricks with abusing HTML tags that could lead to disclosure of sensitive information by revealing the server output to a GET request?
I'm thinking to additionally include a hash of my JWT access token to the GET URL and have the server require that GET requests include that hash, and it must match the JWT token from the cookie. In this way the attacker will not be able to guess a valid GET URL, while also leaking such GET URL will not allow the attacker to get access to my server because he doesn't know the original JWT from cookies. Apart from minor usability issues, this setup looks like a good idea to me, but I haven't googled out anything similar, so I'm suspicious :)
Concept of CSRF attack, it forces the authenticated user to perform unwanted actions on a web application to which he is authorized to.
CSRF attacks ensures to introduce the state change for stateless servers, thefting of data is not involved as GET request would fetch the response to the victim not to the attacker, as victim is authorized to. There is no means that attacker can see the response to the forged request.
A CSRF attack can bring the change to the state of the server but it can't see their results, it is forced to act blindly.
Let's say, CSRF attack can tell the victim browser to request victim bank account balance, but the attacker can't see that balance. This is obviously a pointless attack.
But it is not pointless if, the attacker ask the victim browser to perform transfer of money from victim account to the attacker's account. The success or failure page for the transfer is inaccessible to the attacking script. Attacker is not concerned about the response of success or failure, his main concern lies he want money in his account.
If you are performing GET request to change the state of the server, it may turn out to be risky for you.
"GET http://bank.com/transfer.do?acct=BOB&amount=100 HTTP/1.1", if one such is your request.
Which I believe it would not be.
So you must focus on POST request which should be monitored using CSRF token.
Sharing the link for OWASP rules https://www.owasp.org/index.php/Top_10_2010-A5-Cross-Site_Request_Forgery_%28CSRF%29 must go it once.
Do people typically store permissions in a JWT? I've seen example that might have admin: true or scopes: ['add_foo', 'delete_foo', 'read_foo']. And this seems fine, other that the potentially large size that the JWT could become if there are a lot of permissions/scopes. It seems like it would be really useful as you wouldn't need to hit a DB or cache to get the users permissions as long as the JWT can be verified.
My main question though is how these would be invalidated in the event of a permissions change.
For example, sys admin Joe, revokes the 'add_foo' and 'delete_foo' permissions from user Bob, but keeps the 'read_foo' permission. In this scenario user Bob should not have his token entirely invalidated and need to log back in, he should basically be forced to get a new JWT with the new permissions and carry on as normal.
I've seen examples explaining issuing a new JWT in the event of a password change, but the difference here is that sys admin Joe does the update to user Bob. Thus, there is no opportunity in this workflow for user Bob to get the new token immediately.
Most examples suggest for invalidation maintaining a black list of revoked tokens, or changing a DB record ID so the token is no longer valid, or having a per-user secret and changing that.
I see that all of these would work for the revoking of the token and test that its invalid, but how does the user then get a new token? their current JWT is now invalid? Trying to do anything with it should fail.
I've seen mention of a "refresh token". Are these widely use? Are they secure on the web or mainly used for mobile apps where the refresh token is harder to obtain. It seems like it would be reasonably easy to steal a refresh token via browser dev tools or similar and then someone would have access forever to that account until the unauthorized access was noticed and the refresh token revoked.
Maybe in this scenario forcing user Bob to re-authenticate is not such a big deal? Permissions probably don't change too often.
Thanks, Mike.
You can set expiration date (for Web app we are usually using 15 min - 30 min, for mobile 1 week). When you set Issued at claims parameter ("iat"). Then every time when you validate token you should check the token's "age". If it older than 5 min you load data from DB and create new token with current "iat" value.
When permissions change you should invalidate the issued tokens for this user. There are different techniques to use. See Invalidating client side JWT session
But consider that revoking tokens is not a recommended practice because you lose one of the main advantages of JWT: It does not require server storage.
The objective of Refresh tokens, as defined in Oauth2.0, is allow applications to obtain a new access token without re-authenticate
Refresh tokens are credentials used to obtain access tokens. Refresh tokens are issued to the client by the authorization server and are used to obtain a new access token when the current access token becomes invalid or expires,
If the permissions do not change frequently it may be easier to re-authenticate user, and if they change much consider whether they really should be included in the token
I'm reading on JWT, there are so many tutorials and so many approaches, it's confusing.
I have couple of questions regarding proper usage of JWTs:
1) I keep seeing inconsistent means of transporting JWTs to and from the server. For example, here: one transport method for retrieving the token (via JSON-encoded object in POST body), another method for submitting it (via HTTP header). Why such inconsistency? Of course, it's up to the implementer to choose the methods, but wouldn't it be good practice at least to be consistent and use either only header or only body?
2) The JWT payload contains the information of state because the server is not maintaining it. It is obvious one should keep the size of the payload as small as possible, because the size of JWT is added to every request and response. Perhaps just a user id and cached permissions. When the client needs any information, it can receive it via (typically JSON-encoded) HTTP body and store it in the local storage, there seems to be no need to access the read-only JWT payload for the same purpose. So, why should one keep the JWT payload nonencrypted? Why mix the two ways of getting application data to the client and use both JWT payload and normal data-in-response-body? Shouldn't the best practice be to keep JWT always encrypted? It can be updated only on the server side anyway.
1) I keep seeing inconsistent means of transporting JWTs to and from the server. [...] wouldn't it be good practice at least to be consistent and use either only header or only body?
This may depend on the Client. While a web app can get a higher degree of security by storing the JWT in cookie storage, native apps may prefere local storage in order to access the JWT information. [1]
2) The JWT payload contains the information of state because the server is not maintaining it. It is obvious one should keep the size of the payload as small as possible, because the size of JWT is added to every request and response. Perhaps just a user id and cached permissions. When the client needs any information, it can receive it via (typically JSON-encoded) HTTP body and store it in the local storage, there seems to be no need to access the read-only JWT payload for the same purpose.
The JWT keeps the Backend state, not the client state. The Backend state may be that User 128 is logged in as administrator. This is (in my example) stored in the JWT in the fields Subject and Scopes. Instead of the client sending an ID of a Backend session that contains this information, the info is in the JWT directly. The backend does thus not have to keep a session that stores the logged in state of user 128. If the Client requests information of User 2, the BE may decide that this info is forbidden if the JWT tells that the logged in user has ID 1.
So, why should one keep the JWT payload nonencrypted?
The state is normally not secret to the client. the client cannot trust the information in the JWT since it does not have access to the secret key that is used to validate the JWT, but it can still adjust the GUI etc from the information in the JWT. (Like showing a button for the admin GUI or not.)
Why mix the two ways of getting application data to the client and use both JWT payload and normal data-in-response-body?
See above, the main purpose of the JWT is to keep information the the Backend, not the Client. Once the user loggs in, the Backend ask "Hey, can you hold this info for me and attach it to every request so that I can forget about you in the meantime?" Like if your manager asks you to wear a name sticker on your skirt so that he/she don't have to remember your name. :-) (And he/she signs it so that you cannot alter it without him/her noticing.
Shouldn't the best practice be to keep JWT always encrypted? It can be updated only on the server side anyway.
It doesn't really bring any security unless you store secret information in the JWT, and that bay be better to do server side. The decryption is a bit more cumbersome to decrypt compared to just verifying a signature.
[1] Local Storage vs Cookies
If your API and Website making ajax calls to that API are on the same server (even domain), how would you secure that API?
I only want requests from the same server to be allowed! No remote requests from any other domain, I already have SSL installed does this mean I am safe?
I think you have some confusion that I want to help you clear up.
By the very fact that you are talking about "making Ajax calls" you are talking about your application making remote requests to your server. Even if your website is served from the same domain you are making a remote request.
I only want requests from the same server to be allowed!
Therein lies the problem. You are not talking about making a request from server-to-server. You are talking about making a request from client-to-server (Ajax), so you cannot use IP restrictions (unless you know the IP address of every client that will access your site).
Restricting Ajax requests does not need to be any different than restricting other requests. How do you keep unauthorized users from accessing "normal" web pages? Typically you would have the user authenticate, create a user session on the server, pass a session cookie back tot he client that is then submitted on every request, right? All that stuff works for Ajax requests too.
If your API is exposed on the internet there is nothing you can do to stop others from trying to make requests against it (again, unless you know all of the IPs of allowed clients). So you have to have server-side control in place to authorize remote calls from your allowed clients.
Oh, and having TLS in place is a step in the right direction. I am always amazed by the number of developers that think they can do without TLS. But TLS alone is not enough.
Look at request_referer in your HTTP headers. That tell you where the request came from.
It depends what you want to secure it from.
Third parties getting their visitors to request data from your API using the credentials those visitors have on your site
Browsers will protect you automatically unless you take steps to disable that protection.
Third parties getting their visitors to request changes to your site using your API and the visitors' credentials
Nothing Ajax specific about this. Implement the usual defences against CSRF.
Third parties requesting data using their own client
Again, nothing Ajax specific about this. You can't prevent the requests being made. You need authentication/authorisation (e.g. password protection).
I already have SSL installed does this mean I am safe
No. That protects data from being intercepted enroute. It doesn't prevent other people requesting the data, or accessing it from the end points.
you can check ip address, if You want accept request only from same server, place .htaccess in api directory or in virtualhost configuration directive, to allow only 127.0.0.1 or localhost. Configuration is based on what webserver You have.