This may be something trivial for many of you but I haven't had any luck in understanding the right flow for my usecase. I am building an API for our mobile apps (IOS & Android) and like most of the web applications, the API has certain features/pages(in terms of a website) that can only be accessed by a logged in user. Since sessions are usually discouraged in API construct, I wonder how to track such things in API. My question is, how do I identify that:
User is Logged in from client side. So when a user logs in by sending his/her username and password, server side authorizes the user after verifying from the DB. At this point, what should I send to client that it needs to send me with each request for future identification?
Making sure that I am getting request for the real user...user A, for instance, can't ask for user's B information. In other words what I am thinking is that, if I do things based on a UserID (or some token as it has to have some encryption too) then someone can break my security somehow and ask for content for another user's ID...How do i secure this?
Essentially, I am looking for some guidance for maintaining state in a stateless way.
Try sending a session_id after user is authenticated successfully.
That might be created as an md5 hash from user_name salted by current timestamp.
At server-side I you can create a table session_data(session_id, user_id, last_access_time, session_data), that would map session_id to a user. Session would become obsolete after last_access_time is to old.
This approach isn't perfect for intense user interaction, since you will have to update session_data after every request.
In this case such table could be moved in any fast storage.
There is no such concept in the API development as logged in state, etc... That's why it is stateless. You have to authenticate every request (so send the username and password with every request).
note: You can have session, but it is maintained by the REST client, so the API does not know anything of it.
Related
I would really like some opinions on whether the following is a safe method as user authentication, and if not, please point out it's shortcomings.
React front end
PHP / MySQL based RESTful API on remote server
1) user signs up, data is posted to the API, user is emailed a single use activation link to ensure email is valid before they can access their account.
2) user signs in, API validates the data in all of the usual ways and then sends back a JSON object containing their user ID and an access token.
3) user ID and access token are set in localStorage on the users device upon receiving the data. React then grabs that data from localStorage and uses it to set and control the state in Redux stores providing an App wide Auth state.
4) user ID and access token are sent along with every future request made to the API. In the instances where a user isn't logged in, i.e - they don't supply a valid user id with matching token, they are automatically prevented from requesting anything that requires authentication at the very first entry point of the API. Suitable responses are sent back which in turn update the front end state to reflect a non-logged in user.
5) When the user logs out the access Token is deleted from localStorage.
A bit more detail about some the inner workings :
All tokens are generated server side and stored in the DB, they are random and unique bin2hex(random_bytes(32)) and only valid when supplied with the matching user ID. So changing the user ID in a request will result in a failed auth response, as will supplying a valid user ID with a mismatching or expired token.
Tokens are single use and a new token is generated, stored and then sent back in the response from every authenticated request along with the corresponding user ID. This may be overkill and put a lot of extra strain on the server. Would really like your opinions on this aspect especially please.
Tokens are set to expire in 2hrs regardless. So if the user leaves themselves logged in, they will be automatically logged out after 2hrs of inactivity.
User ID and Token are sent as part of the JSON body of every request (not in the headers). Is this a cause for concern?
At no point (other than sign up and login) is the users password transmitted or stored in localStorage or used by the React frontend. A matching user ID and Token is all that is required to validate the user after the initial authorization.
All connections are made via HTTPS.
Can you spot any glaring security risks in this approach? Am I missing the elephant in the room here?
Obviously the user ID and matching token is as good as supplying the users email and password on every request as far as auth goes, but I can't use PHP sessions or cookies* as the API is hosted on a different domain. This is the best workaround I could come up with without having to go down the JWT or Oauth route.
How flawed it could be in regards to how I am checking and validating data on the API can't be practically addressed here, but assuming that it is all being done correctly is this method secure enough in principle?
I look forward to and thank you in advance for your opinions :)
*without a ton of workarounds which would ultimately be superflous as this App can only be used with modern browsers which all support localStorage.
In my opinion is not save to store the token in the local store,
As said in https://auth0.com/docs/security/store-tokens
Since Browser local storage (or session storage) is not secure. Any data stored there may be vulnerable to cross-site scripting. If an attacker steals a token, they can gain access to and make requests to your API. Treat tokens like credit card numbers or passwords: don’t store them in local storage.
A better option is to use cookies since they are managed by the browser.
I think it's important to say that I don't have any experience in the technologies nominated below, I have some idea what is going on, I've googled a lot, but still - more I google more dumb I feel. :)
Making an app in Ionic 2, users of this app can read/write data about themself in DB.
I am using Wordpress as backend, actually users will change values in the table that was created by some Wordpress plugin.
First problem - I have no experience at all.
Second one - I must understand which user is knocking to the server.
Because user can change only his own data in DB.
I've solved it by creating a script that checks GET request from app & that request has a param with user nickname, so I have turned this script to template and assignined it to the page. ( template was first thing that went to my mind, if you have better idea - please tell me how to do it better! ).
Well now I knew who it is, but I disliked that this so unsecure!
Its only GET request with user name in it and changes to bring into DB.
NOT GOOD.
I've thought that I should send not only nickname but also some kind of a password, so I can check if the user is actually genuine user, well, you know.
But knowing nothing about security, didn't know where to start so I've started googling.
I've find out that there is 'Basic Authentication' - disliked it because password is verry simple to decode (base64) and you must send it with every request (not safe).
Then I thought about crypting pass with strong algorithm like bcrypt & then send it with the request. Disliked it too - because at the end you are always send a password even if strongly crypted.
Now I've started to look in the direction of Auth 1.0
(because saw that wordpress has a plugin for it, I know little about wp however).
But after all I am not so sure that I am doing things in the right way.
I must finish many things, but I am stuck with this security issue and I don't know if it's my paranoia and there is simplier ways to accomplish what I want to do.
Don't have much time, don't want to waste time anymore.
Please, someone who is pro in this stuff give me an advise how to do this thing in the right way!
because I am going crazy with that stuff.
The best practice is to issue an access token from your server to your (or even third-party) client application by the following steps.
A user uses a client application.
The client application asks the user whether to use your service.
The user answers "yes".
The client application opens the authorization page of your service using a web browser. In other words, the client application makes an authorization request to your authorization server.
The authorization page explains to the user that the client application is requesting some permissions and asks the user whether to approve it or not.
The user inputs his/her ID and password into the login form in the authorization page and then presses the "approve" button.
Your authorization server authenticates the user and issues an access token to the client application.
The client application accesses a Web API of your service with the access token.
The Web API of your service checks whether the presented access token is valid or not.
If the access token is valid, the Web API returns a successful response to the client application.
RFC 6749 (The OAuth 2.0 Authorization Framework) defines 4 flows to issue an access token. Check the specification.
Note: I know there are LOTS of other StackOverflow questions dealing with this topic. I've read through many of them, as well as many other websites. I still have the following questions.
So, I'm building a REST API for a new product. At this time the API is entirely for private consumption by our websites and phone apps. However, I'm thinking it might be smart to design the API so that it can be made public in the future.
Authentication
While I've looked at OAuth, I think HTTP Basic Authentication over SSL is plenty secure enough for our API. From what I understand HTTP Basic Authentication over SSL is a completely viable way of authenticating a REST API. It's also quite simple, which is appealing for me since I'm new to API development.
Authorization
If a user logs in to the API using their username and password, they will only be given access to certain parts of the API. Meaning they'll have access to their own content, but not the content of other users. Further, they may be limited to what they can all do.
In addition to the user accounts, I plan to also have other other (non user) accounts for more global administrative tasks. These accounts could potentially have full access to the API.
Is this a good design? OR, is it bad to authenticate a user in this way? Should I only be authenticating my clients (ie. apps) this way?
Sessions
My big question is, when logging a user into our web app, how do I manage their sessions? REST stipulates sending the username and password with each request. Further, REST API's are stateless, so I cannot manage sessions there. However, I need to track that they've logged into the web app somehow. They clearly can't possibly login manually for each request.
One approach is, after a user logs in, we save their login credentials (email & password) to the PHP session. Then, each subsequent request to the API could use those credentials. However, saving usernames and passwords in a PHP session just feels wrong and very unsafe. But if not done this way, how are people managing sessions when interacting with a REST API?
The phone apps are easier, as you can save the user's login credentials into a keychain.
Can anyone help with my design questions?
I know this question is a bit old and maybe you already finished your work, but I'd like to give you some tips. Maybe these could help you or anybody in the future. :)
Authentication
HTTP Basic Auth over SSL is quite simple, that's true, but not so secure than you think. You only have to install 1 "fake" SSL cert on the client and with a man in the middle attack you can sniff the traffic.
How to install a fake certificate? It's not so hard in a browser lot of users just click on the ok when they see the huge red warning screen. On a mobile for example: http://cryptopath.wordpress.com/2010/01/29/iphone-certificate-flaws/
With this solution you only have to intercept the traffic once and you'll have the user's password!
My tip: Generate a temporary password at login and use this in every other requests. So the attacker have to intercept the login process for the password and if you store this pass locally on the phone for example it's much harder. (And of course you can add expiration to it etc...)
Authorization
I don't really understand what would you do. User access management is a good thing, but it depends on the given project.
Session
Not only the REST APIs, teh whole HTTP world is stateless. If you use a PHP session it stores a session id in a cookie on the client side and the browser sends this cookie value every time to the server.
The users don't have to login every time. They log in once and get a token/temporary password etc... and (or if you don't use these stuff) they send you a basic auth header at every requests.
This way you can easily track who sent you the request, because you already now who's that user and you can store and link some data to it on the server.
There are many ways to deal with users. Basic auth is one of them. And check this: OAuth's tokens and sessions in REST
"OAuth tokens are explicitly a session identifier, ..."
You don't have to store the user's password and email, you just have to check the headers/cookies/etc... from the client in every requests.
The phone apps are easier, as you can save the user's login
credentials into a keychain.
They can, but saving the user's real password on a phone is a very bad practice. Save a time limited token is a bit better. :)
In every other languages you can store values if you want. For example if you want to use a Python client for your API: It authenticates and stores a token or something what it needs in a variable and at every other requests it uses this stored data.
One more sidenote:
However, saving usernames and passwords in a PHP session just feels
wrong and very unsafe.
True that's unsafe, but the (real) PHP sessions are stored on the server side and as I said it stores only a single session id on the client side. Anybody who can get this session id, could impersonate the given user. (There are countermeasures for example IP check, etc...)
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 working on integrating Google Apps into my PHP app. I have already a login system that assigns a session ID to a user (after entering username and password), which gets stored in the database when the user is logged in. Session ID's become invalid after a certain time of inactivity (configurable by the user, can be 5 minutes, 15, 60...). That session ID is passed in the url to check if a user is still logged in. When logging out, the session ID is removed from the database.
I let people log in with Google by storing their Google ID in the database, when they log in, I request an access token, query the userinfo, see if the google ID is in the database and if so, assign a session ID to this user. Since I want to be able to query other API's I also store the access token json in the database. When a user logs out, the access token is also removed from the database.
This works, my users are able to log in using their Google account and I can query the API's using the stored access_token, however some things feel clunky of make me feel uncertain about my workflow:
If you force_approval you get a refresh_token, I feel like I should be using this refresh token to get a new access token, instead of removing the old one from the database and entering a new one when the user logs in again. On the other hand, when logging in, I do not know who it is yet, so I don't know which refresh token to use. Maybe I'm misunderstanding what the refresh token is for. Also, I don't really want to force approval every time, so I can't even use the refresh_token in that case.
As said before, users can determine how long their session will last, however, the google access_token always expires after 3600 seconds. It'd be really stupid if users would work an hour on the system and after that the Google API's suddenly fail, forcing them to log in again. The Google OAuth playground shows a checkbox "Auto-refresh token before it expires", but I'm not seeing how to do this. Do I have to use the refresh token here? Or simply request a new token in the background (if I'm not forcing approval)?
At the moment, I'm using the userinfo query (https://www.googleapis.com/oauth2/v2/userinfo) to find the user id, but I can also use the tokeninfo (https://www.googleapis.com/oauth2/v1/tokeninfo). Tokeninfo is not listed in the oauth playground, but the result does show how long the token remains valid (however, I can also calculate this myself). Is one preferable over the other?
I'm storing the entire json object in the database (access_token, id_token, expires_in and token_type) but I feel my app will still work perfectly if I only store the access_token (only problem I foresee is if the expires_in time changes). Do I need to store the id_token for example?
I find the Google documentation (at developers.google.com) sometimes very lacking, if anyone knows any other good sources of information, I'm interested in them as well.
I think it might help if you took a look at the lastest OpenID Connect Specs where concepts like the userinfo endpoint come from. OpenID connect is built on top of OAuth 2. There's quite a lot in there, but it's still probably worth a look. This blog article is also very good (as are others in the same blog).
Unfortunately, I don't think Google's implementation is currently up to date with the latest spec draft so it will probably be a moving target for some time. These things have changed a lot over the past year.
I agree with your first point that you should be obtaining a new access token each time you authenticate a user, rather than refreshing an old one. You don't know who the user is until they have logged in and granted you an access token. In general, the lifespan of an access token is not linked to the user's session. Once issued, your application could theoretically use it to access resources independently of the user's presence. If you want to carry on accessing the resource beyond the token expiry time, then you need to submit the refresh token at that point to obtain a new access token. I'm afraid I don't know what the "auto-refresh" feature is for.
I believe Google's tokeninfo is analogous to the check_id endpoint of OpenID connect, but accepts either an access token or an id token, rather than just the latter. Note that the expiry times of the two may differ. You would typically be able to retrieve more detailed user data from the userinfo endpoint than from check_id, which would normally return the bare user_id.
You shouldn't need to store the id_token. It is a bit like a record of the user's authentication by the authorization server. The access token is what your application will be interested in maintaining once you have validated the user identity.