I am currently planning the restructuring of a web application to separate the API from the application. Right now, users log in to the application by entering their operator ID (username) and password into a standard HTML form and the authentication is done by checking the database table and creating a PHP session (handled using Zend_Session). I'm not sure how to continue doing this after separating the API.
Here is some simplified code to illustrate how things currently work:
// GET https://foo.example.com/module/trips.php
if (isLoggedIn() && isAuthorized($SESSION->operatorID)) {
require 'views/trips.php';
}
// POST https://foo.example.com/module/trips.php?action=take
// ...
// this request can come from AJAX, for example
if (isLoggedIn() && isAuthorized($SESSION->operatorID)) {
$model->assignTrip($SESSION->operatorID, $_POST['trip_id']);
}
Obviously this isn't very RESTful, hence the effort to separate the two. This is what I proposed (still a work in progress):
// GET https://api.foo.example.com/v1.0/trips
echo json_encode($model->getAllTrips());
// POST https://api.foo.example.com/v1.0/trips/:trip_id/operator
$model->assignTrip($_POST['operator_id'], $trip_id);
I understand that REST is stateless. In this simplified example, only the operator should be able to assign himself/herself a trip. How do I enforce this with the API?
I've read many, many questions and articles about authentication with REST APIs and they all talk about OAuth/OAuth2 which seems great for authenticating clients of the API via tokens but nothing about authenticating users of the API client (or perhaps I'm misunderstanding something?) In my case, my API client is still the web application.
My main question: How is the API supposed to determine who the user is? Or is it even supposed to?
Alternatively I have considered doing this in the web application:
// POST https://foo.example.com/module/trips.php?action=take
// ...
// this request can come from AJAX, for example
if (isLoggedIn() && isAuthorized($SESSION->operatorID)) {
// Use cURL to send an HTTP POST request with the appropriate data to
// https://api.foo.example.com/v1.0/trips/6/operator
}
That seems like unnecessary overhead but that's what it looks like in this answer. I thought that after my restructuring I should be doing something like this from the JavaScript:
$.ajax({
type: 'POST',
url: 'https://api.foo.example.com/v1.0/trips/' + trip + '/operator',
data: {
operator_id: 6601
}
}).success(function() {
// It worked!
});
I've looked at GitHub API Authentication as an example and the Basic Usage uses curl -u "username" <api-endpoint-url>. I'm not concerned about using the Authorization HTTP header as this application is already HTTPS only but in this case wouldn't I need to store the password in the locally (e.g. Web Storage or something)?
I've also read this blog post and I'm not sure if that's what I'm supposed to be doing and if so, am I supposed to include the username and password in that hashed blob of data?
Perhaps I am misunderstanding how APIs are supposed to work in general, if so it would be great for someone to clear that up!
I agree that send some header data and store it localy are strange, but, believe, that's the way.
You can take a look to HMAC authentication.
A lot of APIs today use it, or adapt it to work with. You will ever send some user ID in header, concatenated with your hash. The server will recognize the user by that readers.
You don't need to store the password localy, just the hash (or a token) sent by server when the auth request are made.
Clearing all:
Make the API call to authenticate the user
The server will check the user login/password, if all fine it will store a TOKEN and return it on the request.
The client store the token
All the subsequent request will send that token in the header
The server will always check if that token are valid, and, find the current user using the token or another data sent in headers
Related
I am working on building a rest api just to learn and I am stuck on the login flow and how it should work.
Here are some facts about my api so far:
My api is written in php.
I am using http basic auth to get the username and password of the requestor. Once I grab it with $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] and check the credentials against my database table 'apiuser' to authenticate.
I also have a table called 'users'. This table is meant to be the end users that will use the websites and apps that are written on my api.
Here are my questions:
If I want to authenticate a user (not an apiuser) what should my rest api url look like? I have read enough to know that verbs are bad so I am leaning away from https://api.mysite.com/users/login
So should it just be
METHOD: GET
URL: https://api.mysite.com/users
HTTP BODY: {"username":"xxxxxx","password":"xxxxxx}
and just return for success
HTTP CODE: 200
HTTP BODY: {"id_user":"xx","username":"xxxxxx","screenname":"xxxxxxx"}
and for invalid logins
HTTP CODE: 404
I think this is the way to go, because isn't a login attempt really just like running any other GET with some parameters? In other words, would authenticating be any different than doing something like
HTTP METHOD: GET
URL: https://api.mysite.com/users
HTTP BODY: {"age":"72"}
EDIT
This api is intended to be used by only me. The idea is that I write an api and then I can write a backbone.js site, and iphone app, android app etc... on top of it. It is not meant to be for the public. So that is why I avoided diving into OAuth quite yet.
I POST the username and PW to the api:
http://www.mysite.com/api/authenticate/ (username and PW included in the POST collection)
That returns a long, unique token which i generate on the server.
A token is then required in request headers for all other requests. All pages (except authenticate) require a valid token or they return an error.
A login attempt is then a POST because it inserts a token record.
http://www.mysite.com/api/deauthenticate/ destroys the token (assuming a valid token is included in the header)
(also because the token is in the db, I can deauthenticate a user, requiring another login whenever I want - eg, after 10 minutes or 10 hours)
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.
I am trying to implement the Rest approach for designing my Api.
Please go through the work flow below and try to clear my doubts and also point out mistakes-
Client(Web browser)
Rest call from client ->/post /login username/password
Server
/login service checks with the DB if the username & password are correct
Responds ok:200 + sends back data-> X
Client
receives confirmation that user is authenticated + data -> X
Now uses data X for subsequent calls to the server to get User specific info through other service calls
/get/FirstName_of_User/X
or
/get/LastName_of_User/X
now my doubts are the following(what are the best practices for doing the following)
Since for subsequent requests we need to tell the service whose data are we requesting what should the X be ? (Username or temporary token created(does not makes sense since Rest is all about being stateless) or something else ? )
Once this X is returned where should it be stored on the client side so that it can be sued for every subsequent requests ? (Cookie or some other way exists) ?
if this is how i make the subsequent calls
/get/FirstName_of_User/X
if this call is made by someone else too then it would give the result, i want the person just logged in to get the result only..
Reg doubt 3 - i found this link on stackoverflow - Is session used to REST authentication?
which suggests using HMAC and found this link - http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/ which talks about how HMAC can be used for Rest(basically talks about having a private key on both the client and the server and using it to hash the request)..
My doubt regarding this approach is - say i use password as the private key which both the client and server know about.. then on the client side should we just save the password in the cookies fr hashing each subsequent requests ??
Thanks
Any help for any of the doubts is appreciated
PS: i am trying to implement the system using PHP + Mysql
/user/id?access_token=42342342342423
rest apis don't need no SEO, so drop the firstname_of_user, just use id, simpler, cleaner, less to maintain.
Somehow your requirement and what we are implementing in our project looks same except different platform, ours is .net.
Follow the same process for login resource with username and password. Once you decide on the mechanism you want to sign this token its not mandatory that it is always appended in the url.
Instead of sending the token in the URL try it with the authorization header of http protocol. Use Authorization = "Authorization" ":" credentials Ref
This way you can keep your url same but based on the authentication you can serve resources.
You can store this token in cookie for subsequent requests.
Removing token from url solves your 3rd doubt.
Hope this helps you up to some extent.
I'm wanting to make an API quickly, following REST principles - for a simple web application I've built. The first place the API will be used is to interface with an iPhone app. The API only needs handle a few basic calls, but all require authentication, nothing is public data.
login/authenticate user
get list of records in users group
get list again, only those that have changed (newly added or updated)
update record
So, following REST principles, would I setup the uri scheme?:
mysite.com/api/auth (POST?)
mysite.com/api/users (GET)
mysite.com/api/update (POST?)
and the responses will be in XML to begin with, JSON too later.
On the website, users login with email and password. Should I let them get a 'token' on their profile page to pass with every api request? (would make the stand alone '/auth' URI resource redundant).
Best practices for structuring the response xml? It seems like with REST, that you should return either 200 ok and the XML or actual proper status codes i.e. 401 etc
Any general pointers appreciated.
1- for auth, you might want to consider something like http-basic, or digest auth (note - basic in particular is insecure if not over https)
for the urls scheme:
/api/auth is not needed if you leverage basic or digest.
/api/group/groupname/ is probably more canonical
/api/update would generally be done as /api/users/username (POST) with the new data added - the resource is the user - POST is the verb
otherwise, basically your API looks sane, much depends on whether groups are hierarchical, and users must live in a group - if so, your urls should reflect that and be navigable.
2- status codes should reflect status - 200 for OK, 401 for access denied, 404 for not found, 500 for error processing. Generally you should only return an XML record if you have a good request
Authentication in an API always works by sending some authenticating token in the request header. I.e., even when using the separate /auth login approach, you would return some token, possibly a cookie, back to the user, which would need to be send together with every request.
HTTP already provides a dedicated header for this purpose though: Authorization.
The most basic HTTP "Authorization" is HTTP Basic access authentication:
Authorization : Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Digest Authentication is another, more secure, scheme. You can use this header field for any form of authentication you want though, even your custom implemented authentication.
Authorization : MyCustomAuthentication foo:bar:n293f82jn398n9r
You could send the aforementioned login token in this field. Or you could employ a request signing scheme, in which certain request fields are hashed together with the password of the user, basically sending the password without sending the password (similar to digest authentication, but you can use something better than md5). That obliterates the separate login step. AWS employs this method.
For an API in general, make good use of the HTTP status codes to indicate what is happening.
You're generally on the right track. The URI scheme should be based around the idea of resources and you should use an appropriate method to do the work.
So, GET to retrieve info. POST (Or maybe PUT) to create/change resources. DELETE for well, delete. And HEAD to check the metadata.
The structure of your XML doesn't have much to do with a RESTful API, assuming it doesn't require state management. That said, you have the right idea. If it's a good request, return the desired XML (for a GET request) and status code 200. If it's a bad request, you may also, and in some cases needed to, return something other than just the status code. Basically, get familiar with the HTTP spec and follow it as closely as possible.