I am currently implementing an OAuth authentication 3 legged strategy using 2.0. I have come across a problem:
What's the best way to remember the client's session when logging in using Oauth.
Currently what I'm doing is setting a cookie on the client that matches my session ID on the server. This is of course equivalent to a normal cookie session based login. Then in the session, I keep track of the access token that I got when I used the Auth Code and exchanged it for the access token.
As you can see, state is kept in sync between the client and the server via the cookie/session id, and the access token is kept only in the server and in relationship to the session id.
However I've read that this is insecure, and that OAuth should be stateless (restful) style, so cookies should not be required, especially if the client is a machine client and not a browser client. Some resources have mentioned that the client should store all the necessary credentials in order to authenticate any request to the app. Does this mean I should store the access token in the browser's header? What about the auth code from the redirect, should this be stored on the browser's header as well? (And should these codes/tokens be encrypted/signed on the browser's headers) (and how would you do this using PHP?)
Resources like this: http://sitr.us/2011/08/26/cookies-are-bad-for-you.html says a client side rich javascript app could keep track of the access token and pass it in on every XHR request? But of course not every client is a javascript app such as machine clients.
You should not store the token in a regular session.
The idea of it being stateless is that each request carries all the required validation information.
Of course this may require more work on the client side in order to ensure all requests carry all the required data.
One of the benefits of REST's statelessness is that it is simpler to have a distributed implementation. Every request has all the necessary data so you don't even need to hit the same server twice, each server can validate on its own.
Related
I am very new to OAuth and I intend implementing an api for a frontend only (html and JavaScript) web app with login abilities using laravel Passport. Both the frontend app and the API server will reside on different servers. I have read a lot about different grants but still confused about which will be best suited for what I intend doing. Are the access tokens going to be stored on the front end (using local storage or cookies)? I am just confused about where to even start from.
I would suggest using the Implicit grant which is designed for browser applications. You can keep tokens in the sessionStorage (or the localStorage if you want to share them among browser tabs). OAuth2 tokens should sent as Authorization: Bearer tokenstring HTTP request headers, so cookies are not a good place for storing them.
There are two token types you can use:
Access token - if you want to use the token for authentication, access tokens hold scopes - information what actions the client is allowed to perform on behalf the person who was authenticated. Access tokens are often just random strings, so to validate it, the backend needs to ask the /token endpoint to get info about their validity and about the person who authenticated it.
ID token from OpenID Connect (OAuth2 extension) - in JWT form, ID tokens hold info about the person who authenticated them, can be validate offline, but cannot be used for authorization - they don't hold any scopes.
Bot token types have limited lifetime, you will have to get new token before the original one expires (using &prompt=none request see the OpenID Connect RFC).
I'm working on a Single-Page-Webapp (SPA) with angularjs (JavaScript) in the frontend and a php rest api in the backend.
I do a lot of ajax calls to the server for example to submit a new story. There the security question came up. The server needs to identify the request. Since it's an SPA only one client (the frontend) should be have the permission to do this request.
I've been googleing for days to find a way to identify the client. I saw that i could send a clientid in the header of the ajax call but that would not be secure since the frontend is in JS and all the JS code can be seen by the user.
Example:
$http.post("some/url", somedata, {
headers: {
"ClientId":"someidforthisclient"
}
});
a hacker could look into the JS code and copy the ClientId. With that he could make ajax calls and the server would think this request is valid.
So my question is:
How can i identfiy the client in the server but with the guarantee that the ClientId (or a security token etc.) can not be seen by the user?
How can i identfiy the client in the server but with the guarantee that the ClientId (or a security token etc.) can not be seen by the user?
You cannot. It is absolutely impossible. For all intents and purposes, as far as the server is concerned, the client application and the user of it are one entity.
You have to trust your users, not their software.
All you need to do is expose the api of login and registration to the users. For any other api access, first you need to authenticate if user is logged in/active.
For authentication you can store user credential in session :
Now user credential will be sent to the api on each request and you will be able to authenticate before processing the request.
You should at the same time encrypt user credential being saved in session so that no one can read that from browser console.
I followed this article on API key authentication with Symfony:
http://symfony.com/doc/current/cookbook/security/api_key_authentication.html
It explains the authentication part well, but it doesn't seem to explain how state between requests works outside of a normal session.
But in some situations (like an OAuth flow), the token may be sent on
only one request. In this case, you will want to authenticate the user
and store that authentication in the session so that the user is
automatically logged in for every subsequent request.
That makes sense but how is the user linked back to the session on subsequent requests, if a token is only provided on the first? I can't use a session cookie because CORS restrictions won't allow me to.
What I'm basically trying to achieve is an API that I can POST login credentials to, in return for an access token that allows me to link requests back to a session.
Can anybody help fill in some of the blanks, or suggest a better way of doing it?
That makes sense but how is the user linked back to the session on subsequent requests, if a token is only provided on the first?
If you use the native session handler, your session and session id as well as a session cookie is sent to the client automatically by PHP's session handler, as soon as you request the session in Symfony.
I can't use a session cookie because CORS restrictions won't allow me to.
Then you can't use a authentication mechanism that provides only at the very beginning (first request) a security key, without sending any other api key in subsequent requests.
What I'm basically trying to achieve is an API that I can POST login credentials to, in return for an access token that allows me to link requests back to a session.
Then do exactly what the linked documentation is doing. Provide additionally a route (not protected) for everyone that accepts credentials and returns a api key. That api key is then used in all subsequent requests, as described in the linked documentation.
I'm writing a RESTful Webservice with the Slim Microframework and use GET for reading data from a mysql database (select query) and also POST/PUT/DELETE for insert/update/delete rows in the database.
My question is now, is this not a big security issue if everybody is able to write or delete data in the database? But how could I prevent this, I thought the ST in REST stands for state transfer (so the webservice is stateless), which is a contradiction to a state like being logged in or not. And if I would pass some login data with the client which is allowed to write in the database, couldn't a bad guy catch the logindata and fake requests with it and for example delete all entries?
So, whats the normal way to go with this, the only Slim Framework examples I had found always show the route examples, but not how to secure it.
Are there also some opportunities in the Slim Framework to implement this what I need? It should be as easy as possible and the request should be responded nearly as quick as without an authentification or similar. There are no sensitive data like passwords, for me it would be enough that not everybody with a cURL commandline tool can delete all rows or things like that.
Would be great if anybody could explain me what to do and/or give some examples. I also need to know, what I maybe will need to change at the clients which are allowed to send the requests.
Lots of thanks.
Each request has to be authenticated and authorised.
People often get tied up with the word 'stateless'. This really just means that from one request to the next, the RESTful service has no prior knowledge of the users state.
BUT, the service is obviously allowed to be aware of the authenticated user that has just made a request, else how would it decide if it should allow access?
Therefore, you can 'store' the authenticated user in some variable during each request. Then it's up to you how you use this information to authorize the request.
I like to keep it simple and have all my users as a resource in my URI chain. They make requests like users/{username}/someresource.
I authenticate using http basic authentication (over SSL) and authorise based on the URI. If the request failed authentication, its a 401 Unauthorized Request. If the URI {username} and authenticated {username} do not match, the request is a 403 forbidden. If it is authenticated and authorized, the request is allowed (http code dependant on http verb)
Now that's the web service covered, now on to the web service client. This of course HAS to store state, otherwise your user would have to log in every time they make a request.
You simply store the users session in the application (as per normal session management) with the addition that you store the username and password (encrypted of course) in the session. Now every time a request is made, your web service client needs to retrieve the username and password, and send it with the request to your web service.
It will be stateless, in the sense that there won't be a session or a cookie, really. You'd normally issue out a key that would be required for INSERT/UPDATE/DELETE.
It is then up to you to pass the key with each request and to determine when a key should expire.
It would be as safe as normal http authenticated sessions. These use a cookie etc to authenticate the connected user to the stored session state.
A stateless service would be no different - the token is passed to the service just as a token is stored in a cookie for normal http. If you are worried about sniffing (IE man in the middle attacks) you would secure the link via SSL.
The authentication token generated by the service would be encrypted and would include a salt which is also verified on the server for each request. You could also limit the session time to suit your paranoia, and also check changes in source IP, user agent etc and expire the user's token if these change.
I recently ran into similar problem. As recommended by people here, I have decided to go with OAuth Authentication.
I am using HybridAuth A php wrapper for OAuth and out of the box sign in solution for Facebook, Twitter, Google, LinkedIn, etc.
I am developing a mobile application using PhoneGap which will communicate with a server(PHP) via ajax requests.
On the server side(PHP)
Something like https://example.com/retrieveData.php
will get the user id via $_POST['user_id'] and return some sensitive information about the user as JSON.
And on the client side(PhoneGap-Javascript)
that JSON output will be parsed and will be used in the application.
My concern is that if someone steals this url ( https://example.com/retrieveData.php ), he can manually send fake post requests and can steal the returned user information?
How can I secure this communication?
My concern is that if someone steals this url ( https://example.com/retrieveData.php ), he can manually send fake post requests and can steal the returned user information?
You are right to be concerned. Anybody can send a message to that URL, and get the result unless you check some part of the request that authorizes the request.
For example, you could authenticate to check that the request comes from the user and then authorize the request based on the idea that the user should have access to that info.
Alternatively, you can authorize based on something that only a valid requestor would know via a shared secret and rely on the https part of that URL to prevent shared secrets from becoming public. You give out the secret to trusted partners, and when you generate a web form via PHP (also protected via HTTPS), you include a hidden input containing the shared secret. This is how XSRF protection typically works.
You should think about the following:
Who should legitimately be able to reach this page? Logged-in users interacting via your phone app, partners who can protect a secret, web API users?
What credentials do they have for using other parts of your server? Log-in cookies? XSRF tokens? Partner tokens?
What parts of your app are sent only over secure channels like https?
If all of (1) is satisfied by some subset of credentials in (2) and those credentials are only ever sent over (3) then you just need to check (2) in your page. Otherwise, you need to rework your application architecture until that is true.
OWASP has a Guide to Authorization that might come in handy and they also have a number of pages on reviewing authorization code but most of the examples are not PHP specific.
Of course he can send any post request he wants. The only possible way to get around this is with authentication that the server knows about, i.e. the client has to send you something hard to guess and that starts a session in the server.
As other answers suggests, following is the strategy to make your webapp more secure :-
The most basic rule, use secured protocol(https)
Authenticate
your user through username and password
Most of the
features/operations of your app primarily must require user to be get
authenticated.
Apart from authentication, Maintain Access Control
List for your app, which decides authorities each user role
have(Assuming that you divides your users into different roles).
Prior to performing any operation on behalf of user, check if user is
authorized to do so.
Don't rely only on client-side validation.
Perform validation at server side also.
Send csrf_tokens along
with your response, along with session cookies.
Never send any
confidential information in cookies.
Hope it helps.