Design of Restful API with HTTP Basic Authentication - php

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...)

Related

Mobile App: users writing to DB how to be sure they can(authentication)?

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.

REST API - User session Management in a stateless way

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.

Auth tokens for REST Api in PHP

I am new to PHP :). I am creating a REST API with PHP which would be used by mobile clients(Android and IOS). Currently the PHP website(yii) allows users to login with username and password(hashed and stored in DB). The way I think of implementing this is, I can have a login REST api call that authenticates the user and generates a token(some random number or sessionid) and sends a hash of that token to the client. The client then can pass that token on the http header everytime on the REST api call and the api methods will validate this on every call?
Now,
I want to know if there are any disadvantages of this approach?
Also are there any PHP examples of how to do this?
How does this token ensure security? Can someone sniff this token and send it in the request and the server will still allow it? Or Assuming i expire the token with time, should the mobile again authenticate to get a new token?
My answer isn't going to be the only one and I am sure you will get a lot of feedback on such a question.
First the hash. I wouldn't suggest doing it this way. The hash can be snitched in route by man in the middle attack etc. Generally sensitive information in the URL is a bad idea.
Why not use a common session? Authorize on the first call... then the session have been created on the server and the caller... this way you ensure that requests coming next is authorized.
The user/service/server can simply refer to the session cookie created and by doing so be validated. This way is much more secure and doesn't expose sensitive information.
And.. use HTTPS if possible of course... otherwise the information is also acceptable to attacks. It all depends on what level you want security. You can stack layers of security... but that might not make sense if your sending information about cats over the line :)

PHP RESTful Webservice with Slim Framework, Authentification needed or against statelessness?

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.

Can a web server login to external app and pass the cookie to user's browser?

I'm trying to implement single sign-on for a web portal. I've written some code to send a POST request containing the user's login credentials to an external web app to log the user in. (Don't worry, this is all over SSL)
The HTTP response from the web app contains a cookie for the user's login. Is it possible for the web portal server to then pass that cookie to the user's browser? Or is that impossible since the web app is on a different subdomain? I understand there are some security measures built into cookies.
Short answer: NO.
The HTTP server can indeed log into the other service and pass the service's cookie back to the user, but the browser will set that cookie's domain to be the HTTP server's, not the remote service's. There's no way for 'server A' on 'domain A' to make a cookie appear to have originated from 'server B' on 'domain B'. If it were possible, it'd be trivial to steal everyone's authentication cookies for their bank, facebook, myspace, etc...
There are indeed things like cross-domain policies build into modern browsers.
However once upon a time, I created a single login techlology for my own website.
There is a trick you can do. First, on the main site where the users have their
login information, have them a secret generated key. With this unique secret
key to every user, pass them to the other site like
www.abc.com/secret_key
from this secret key, your other website should be able to pull the needed information
like username, profile picture & stuff like that and should create the session on that
domain. So you would have the session created for the opposite domain.
If you still need to pass something back, I would recommend you to go a way that
incorporates RPC over PHP and post something back to your major domain.
This should solve your problems. If you want I can attach some example code.
Note: The security here is in the secret key. Since it's a unique generated key
for example, a md5 hash, it's hard to replicate this. So there is no such thing
like someone could reprocude the secret_key and then login to your site as someone
else.
You should also note that, the secret_key api should only be able to get the
needed information so that not too much information is gathered on the other side.
Why reinvent the wheel? I think that you can find OpenID implementations for PHP. For the consumer and the provider.
You can restrict your OpenID-logins to your domains only if you don't want them to be used elsewhere.

Categories