I am just woundering, how we can use RESTful architecture/webservice to implement online shopping kind of application ?
Say we want to build anything like Amazon where user can login and do shopping. First time, we will perform authentication using HTTP Basic or any other security mechanism, which is fine.
Now, when user made a second request he need to send some authorization code or sessionId or something else so that server will know this is the same user which has logon earlier. But, RESTful webservice is stateless so we are not suppose to store old session related stuff. In that case how we can authenticate user ?
I read something about cliet and server certificates but it is applicable to application where two different services are communicating with each other. Am I correct ?
I am new to webservice :-) so this type of silly question came to my mind.
The http basic auth stores the username and password on the client side, and it sends it again with every request. So by REST you have to send these identification factors and authenticate by every request...
You can cache the authentication mechanism if you want it to be faster...
This is an important thing by REST... REST stores the session on client side, not on server side... If you want store something important on server side, then it has to be a resource or a property of a resource...
If you allow somebody to write 3rd party application (another client for your REST service), then the user should accept that this 3rd party application can send requests in his/her name. Ofc. the user does not want to share his/her password, so give permissions to 3rd party applications is a hard stuff. For example oauth solves this problem...
The basic concept by 3rd party applications (clients), that you ask the user whether it allows them to send certain requests or not. For example by facebook it asks, if you want share your identity, list of acquaintances, etc... and you allow to send posts in your behalf, etc... After you clicked ok, the REST application should store that information and give the client permissions to your account. How to check who sends the requests? Ofc. CSRF is not allowed, so the 3rd party client cannot send a cross domain request on your behalf with the client you are using. So it has to send its requests trough a different connection, probably with curl. What should it send? Ofc. the request details. What else? Its identity (an api key) and your identity. This is the most basic approach.
There are other solutions. You can use a similar approach to what you are using by storing passwords in a database. You store only hashes of the passwords hashed with a slow algorithm. By the authentication you create the hash again on the given password. When the stored hash is equal with the newly created, then the application accepts the identity and grants access to the account. You can use the same approach by requests. The 3rd party client requires a hash for a request. After that it sends the request with the hash it got, and by getting the request, the server compares that hash with the hash it creates based on the content of the request. If they are equal, the request is valid. This is cool stuff, because it prevents a CSRF attack on a 3rd party client as well...
I guess there are many other, more complex approaches, I don't know, I am not a security expert and probably you won't be either. You just have to understand the basics and use a tool for example oauth if you want to allow 3rd party access to your api. If you don't want that, then probably you don't need a REST application, just a simple web application... That depends on your needs, visitor count, etc...
Related
I've read now alot about oauth 2.0 and its use cases (flows).
Now i got these two scenarios:
User logs into our client and with his id and pw, the client is then doing the api calls.
Foreign system with no user data wants to access servers web api.
If i am not wrong i would suggest using for 2. the "Client Credentials flow"
and for 1. I would use "Implicit authorization grant flow".
I have the information about the chosen flows, from http://tutorials.jenkov.com/oauth2/authorization.html
So am i right about this decision or is there a better alternative i have not seen?
Yes you are,
In general when a client (be it your own web client or third party client) wants to access user's data, then they must pass access token which they have obtained during authorization by using any one of the flow (authorization_code or implicit)
And when third party system wants to access data which is not user related or least not sensitive , then you just need some way to identify which client is making the request, its useful for validation, rate limiting etc.
So Client Credentials flow works in your case.
I am developing several Web Services that will be accessed by a mobile application. I have several requirements:
Each user will need to sign in with their own User ID and Password (the same User ID and Password they use to sign into the website).
Every Web Service request will need to be authenticated to ensure that the request is coming from the mobile app(s).
Every Web Service request will need to authenticate the user, since there is user-specific fucntionality built in, and access will need to be blocked if the user's account is disabled.
Let's assume that OAuth is not an option.
In order to ensure that Web Service requests are coming only from the mobile app(s), I am planning to use HTTP Basic Authentication in IIS (the mobile app(s) will need to have a User Account setup in Windows Server and the mobile app will need to store the User Name & Password and pass these in the header).
Next is the User Authentication for each Web Service request. Would it be suitable to encrypt the User ID, Password, and some shared secret key (a "pepper", of sort) with AES-256, pass that encrypted string as a parameter with each request (over HTTPS, of course), and then decrypt and parse it on the server to authenticate? This is the existing plan, but something just doesnt seem right about it - like it's not "secure enough".
What else can I do to properly authenticate users for Web Service requests?
I recently went through this problem and asked opinions from a group of senior people about how they solve the problem. Opinions were varied, but one consistent feeling is that your level of security depends on the use case of your application. Are you doing online banking or storing medical records? Then your security needs may be quite high. Social networking? Maybe not so much.
Basic Authentication is generally fine when encrypted over SSL, ColdFusion works well with it. If you use Basic Auth, make sure to encrypt your traffic with 1024-bit keys or better. Don't authenticate every request with username/password - that's unnecessary. Authenticate the first request, set a session token, and rely on the session token for your identification of users.
Set a polling mechanism from the client to the server to keep the session alive - set the session timeout to 30 minutes and the polling frequency at 25 minutes, for example. Otherwise you may need to re-authenticate expired sessions. Again, how you approach this part of the solution depends on your paranoia level, which depends on what kind of data/app you are dealing with.
Cookies, and therefore sessions, should work fine in iOS apps. If you use sessions to verify identity after authentication, make sure your session cookies are memory-only (set at the server level).
Check the SSL implementation of your server against the Qualysis SSL Test:
https://www.ssllabs.com/ssltest/
The report will give you a surprising amount of detail about the strength of your SSL implementation.
Lastly, consider implementing two-factor authentication to combat password theft.
If you ignore the SSL advice and plan on encrypting your password and communicating over an insecure channel, look at the Kerberos protocol for a well-known example of how to authenticate securely:
http://en.wikipedia.org/wiki/Kerberos_%28protocol%29
Yes, you can use Basic Authentication but that means the client will need to store the username/password in plain text, and also send them over in plain text. Sending part is sort of fine if it's under HTTPS, but storing username/password in plain text may not be a good idea, unless you're using some secure key store.
Let's assume you have decided that Basic Authentication is the way to go, and you want to make use of the official CF way of supporting that, then you can use CFLOGIN.name & CFLOGIN.password. You may also check out Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion. In the remote cfc side, always validate the username/password, or return some sort of token and asks the client to use that token going forward. The token can be cfid+cftoken if you like, or even roll your own that never expires. If you use cfid+cftoken, and send them over as cookie or in body along with your web service call, I believe you can resume the session if you so choose.
My company provide services to other websites. I would like to be able to give them a simple snippet of code to embed in their site (like a widget) that will send a query to the service I'm implementing, receive a response and render the results in the page. I'd like to minimize their effort, and only give them the smallest snippet possible. This is also why I'd like to keep it all client side.
The problem is that I'd like to make sure that the call is actually made by my clients and not by anyone else who copied the code from the site. I looked into the web client oauth2 flow, but it seems that it does not enable to authenticate the client. It does say that there's a way to validate the client by comparing the callback URL to a URL that the client registered with my service.
My Questions:
Is there any better approach?
Is the oauth2 client side approach, including the method described to validate the client, sufficiently secure?
If I go for the suggested implementation, what should I pay attention to?
You could use the Client Credentials Grant Authorization as defined in OAuth-2.0. This would allow you assign a separate Client Token and Client Secret for each separate client and they send in the tokens to get an access token and use the access token to request the data.
Or you could just skip the OAuth all together and use SOAP WS-Security with certificates assigned to each client to authorize the web service.
When designing REST API is it common to authenticate a user first?
The typical use case I am looking for is:
User wants to get data. Sure cool we like to share! Get a public API key and read away!
User wants to store/update data... woah wait up! who are you, can you do this?
I would like to build it once and allow say a web-app, an android application or an iPhone application to use it.
A REST API appears to be a logical choice with requirements like this
To illustrate my question I'll use a simple example.
I have an item in a database, which has a rating attribute (integer 1 to 5).
If I understand REST correctly I would implement a GET request using the language of my choice that returns csv, xml or json like this:
http://example.com/product/getrating/{id}/
Say we pick JSON we return:
{
"id": "1",
"name": "widget1",
"attributes": { "rating": {"type":"int", "value":4} }
}
This is fine for public facing APIs. I get that part.
Where I have tons of question is how do I combine this with a security model? I'm used to web-app security where I have a session state identifying my user at all time so I can control what they can do no matter what they decide to send me. As I understand it this isn't RESTful so would be a bad solution in this case.
I'll try to use another example using the same item/rating.
If user "JOE" wants to add a rating to an item
This could be done using:
http://example.com/product/addrating/{id}/{givenRating}/
At this point I want to store the data saying that "JOE" gave product {id} a rating of {givenRating}.
Question: How do I know the request came from "JOE" and not "BOB".
Furthermore, what if it was for more sensible data like a user's phone number?
What I've got so far is:
1) Use the built-in feature of HTTP to authenticate at every request, either plain HTTP or HTTPS.
This means that every request now take the form of:
https://joe:joepassword#example.com/product/addrating/{id}/{givenRating}/
2) Use an approach like Amazon's S3 with private and public key: http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/
3) Use a cookie anyway and break the stateless part of REST.
The second approach appears better to me, but I am left wondering do I really have to re-invent this whole thing? Hashing, storing, generating the keys, etc all by myself?
This sounds a lot like using session in a typical web application and rewriting the entire stack yourself, which usually to me mean "You're doing it wrong" especially when dealing with security.
EDIT: I guess I should have mentioned OAuth as well.
Edit 5 years later
Use OAuth2!
Previous version
No, there is absolutely no need to use a cookie. It's not half as secure as HTTP Digest, OAuth or Amazon's AWS (which is not hard to copy).
The way you should look at a cookie is that it's an authentication token as much as Basic/Digest/OAuth/whichever would be, but less appropriate.
However, I don't feel using a cookie goes against RESTful principles per se, as long as the contents of the session cookie does not influence the contents of the resource you're returning from the server.
Cookies are evil, stop using them.
Don't worry about being "RESTful", worry about security. Here's how I do it:
Step 1: User hits authentication service with credentials.
Step 2: If credentials check out, return a fingerprint, session id, etc..., and pop them into shared memory for quick retrieval later or use a database if you don't mind adding a few milliseconds to your web service turnaround time.
Step 3: Add an entry point call to the top of every web service script that validates the fingerprint and session id for every web service request.
Step 4: If the fingerprint and session id aren't valid or have timed out redirect to authentication.
READ THIS:
RESTful Authentication
Edit 3 years later
I completely agree with Evert, use OAuth2 with HTTPS, and don't reinvent the wheel! :-)
By simpler REST APIs - not meant for 3rd party clients - JSON Web Tokens can be good as well.
Previous version
Use a cookie anyway and break the stateless part of REST.
Don't use sessions, with sessions your REST service won't be well scalable... There are 2 states here: application state (or client state or session s) and resource state. Application state contains the session data and it is maintained by the REST client. Resource state contains the resource properties and relations and is maintained by the REST service. You can decide very easy whether a particular variable is part of the application state or the resource state. If the amount of data increases with the number of active sessions, then it belongs to the application state. So for example user identity by the current session belongs to the application state, but the list of the users or user permissions belongs to the resource state.
So the REST client should store the identification factors and send them with every request. Don't confuse the REST client with the HTTP client. They are not the same. REST client can be on the server side too if it uses curl, or it can create for example a server side http only cookie which it can share with the REST service via CORS. The only thing what matters that the REST service has to authenticate by every request, so you have to send the credentials (username, password) with every request.
If you write a client side REST client, then this can be done with SSL + HTTP auth. In that case you can create a credentials -> (identity, permissions) cache on the server to make authentication faster. Be aware of that if you clear that cache, and the users send the same request, they will get the same response, just it will take a bit longer. You can compare this with sessions: if you clear the session store, then users will get a status: 401 unauthorized response...
If you write a server side REST client and you send identification factors to the REST service via curl, then you have 2 choices. You can use http auth as well, or you can use a session manager in your REST client but not in the REST service.
If somebody untrusted writes your REST client, then you have to write an application to authenticate the users and to give them the availability to decide whether they want to grant permissions to different clients or not. Oauth is an already existing solution for that. Oauth1 is more secure, oauth2 is less secure but simpler, and I guess there are several other solution for this problem... You don't have to reinvent this. There are complete authentication and authorization solutions using oauth, for example: the wso identity server.
Cookies are not necessarily bad. You can use them in a RESTful way until they hold client state and the service holds resource state only. For example you can store the cart or the preferred pagination settings in cookies...
Hey folks, this seems to have been discussion fairly often but I want to make a simple, watered down question around doing authentication with RESTful services. The scenario is as follows:
There is a system that houses registered users for an application. The system exposes a RESTful API for accessing these users.
There is a front-end application that has a login form. The application can either be internal, or external.
The front-end application needs to use the data in the User system to authenticate a user.
The question now is how to authenticate a user whose credentials (username/password) are entered in the client application against the data in the User system such that it is secure and performant? For the sake of this question, suppose the client application is internal to some sort of Intranet but the applications will not reside on the same machine and may only communicate through the service.
I understand the idea of having the application being "hypermedia driven" but we should be able to provide filtering/searching services. For example, consider the resources and API as below:
http://example.com/users
GET - retrieves all users (paged, hypermedia driven)
POST - creates new user
PUT/DELETE not supported
http://example.com/users/[id]
GET - returns a full representation of a user with id = {id}
PUT - updates user, takes in any predefined media type
DELETE - deletes the user (with appropriate authorization)
POST not supported
Based on the above, my idea would be have the client application GET on the user listing, filtering by username. The service will return the hashed password and salt to the client, the client will perform the authentication.
Thoughts?
If I understand your question correctly, you are looking to implement a generic service that will handle authentication, so that you can re-use it for different applications.
I suggest you take a look at OAuth which has been built for precisely this problem domain.
Passing the username and the salt back is unnecessary and a real security risk.
Perhaps you could consider this approach:
Have the client pass the username and password to the server via Basic Authentication
The server fetches the encrypted password for the username along wiht the salt
The server encrypts the given password using some encryption method, using the salt to assist the algorithm (Ruby code follows):
def User.authenticate(login, password)
ok = false
user = User.find_by_login(login)
if user
#
# user contains the salt, it isn't passed from the client
#
expected_password = hash_password(password, user.salt)
ok = (user.password == expected_password)
end
return ok
end
There are multiple places to use this kind of approach but I like to do it in Rack.
Last point, do it all on a HTTPS connection
Stormpath
Stormpath company dedicated to providing a user login management API and service for developers. They use a REST JSON approach.
There are some other companies that seem to dabble in this new area of authentication-as-a-service, but Stormpath is the only one I know of that is dedicated to it.
First, you don't want the client to perform the authentication, as it then would be trivial to write a client that breaks into your service.
Instead, just use an authentication mechanism like HTTP Basic or HTTP Digest.
Note that if you're using Java, the Restlet framework provides interceptors, called Guards, which support these and other mechanisms. I highly recommend Restlet.
Mozilla Persona
Since this question was posted, the Mozilla Foundation (the maker of the Firefox browser) has taken on the problem of simple user authentication. Their solution is Mozilla Persona, "a sign-in system for the Web". Designed to be easy for users and for developers. The user's identity is an email address. See Wikipedia article.
Update
Mozilla has basically given up work on Persona but not quite killed the project.