I am just playing around with google app engine, webapp2, and python; I am just building a small toy app for fun. A small side note, using ndb for google app engine datastore.
With building a small webapp, comes sessions.
I was reading the webapp2 documentation on sessions, as well as the most popular threads on this website on how to setup sessions. What I don't get about this process is this small piece of code in the config.
config = {}
config['webapp2_extras.sessions'] = {
'secret_key': 'my-super-secret-key',
}
I am pretty new to web development. However, building other smaller apps with this same framework, I done the following to build somewhat secured hashed cookies.
user_key = user_key.id()
user_cookie = self.request.cookies.get('user_cookie', None)
and
self.response.headers.add_header('Set-Cookie','user=%s|%s' % (user_cookie, hash_string(user_cookie)))
self.write('Thank you for sigining up! And, welcome %s' % user.name)
Is that what the first bit of code above for the config is trying to accomplish?
In other words what is this secret key for?
Also, lets say I want to set the 'sessions' cookie to the user id.
Would the code below be the correct way to do this?
self.session[name] = user_key.id()
session_info = self.session.get(name)
Thank you.
The secret_key is used by the server to digitally sign the cookie data that you are reading when you are calling self.request.cookies.get('user_cookie', None).
The cookies are continually passed from client to server along with the digital signature. When the client presents the cookie values to the server with each request it does so with the digital signature given by the server. Each time the server signs the current cookie values, if the signature passed in by the client does not match the current server values the server knows the parameters of the cookie have been tampered with. This guards against a malicious client trying to impersonate another user or otherwise perform an unauthorised action.
This scheme only works if the key is only known to the server, otherwise any client could also sign cookies that the server would accept. Hence secret_key.
The default signature algorithm in webapp2 is HMAC-SHA1.
Also, quickly, when I look at the cookie set by instantiating sessions, it is an extremely long string
This is the code that the server uses to authenticate a cookie if you are curious. You'll notice that the cookie is base64 encoded json document.
Now I suppose that the value of secret_key can then be any string that you'd like it to be, correct?
As they spell out from RFC 2104 on this security thread any string of 20 or more randomly chosen bytes should do for HMAC-SHA1.
Also, lets say I want to set the 'sessions' cookie to the user id
I think this is probably the example you are looking for.
Related
My web application's authentication mechanism currently is quite simple.
When a user logs in, the website sends back a session cookie which is stored (using localStorage) on the user's browser.
However, this cookie can too easily be stolen and used to replay the session from another machine. I notice that other sites, like Gmail for example, have much stronger mechanisms in place to ensure that just copying a cookie won't allow you access to that session.
What are these mechanisms and are there ways for small companies or single developers to use them as well?
We ran into a similar issue. How do you store client-side data securely?
We ended up going with HttpOnly cookie that contains a UUID and an additional copy of that UUID (stored in localStorage). Every request, the user has to send both the UUID and the cookie back to the server, and the server will verify that the UUID match. I think this is how OWASP's double submit cookie works.
Essentially, the attacker needs to access the cookie and localStorage.
Here are a few ideas:
Always use https - and https only cookies.
Save the cookie in a storage system (nosql/cache system/db) and set it a TTL(expiry).
Never save the cookie as received into the storage but add salt and hash it before you save or check it just like you would with a password.
Always clean up expired sessions from the store.
Save issuing IP and IP2Location area. So you can check if the IP changes.
Exclusive session, one user one session.
Session collision detected (another ip) kick user and for next login request 2 way authentication, for instance send an SMS to a registered phone number so he can enter it in the login.
Under no circumstances load untrusted libraries. Better yet host all the libraries you use on your own server/cdn.
Check to not have injection vulnerabilities. Things like profiles or generally things that post back to the user what he entered in one way or another must be heavily sanitized, as they are a prime vector of compromise. Same goes for data sent to the server via anything: cookies,get,post,headers everything you may or may not use from the client must be sanitized.
Should I mention SQLInjections?
Double session either using a url session or storing an encrypted session id in the local store are nice and all but they ultimately are useless as both are accessible for a malicious code that is already included in your site like say a library loaded from a domain that that has been highjacked in one way or another(dns poison, complomised server, proxies, interceptors etc...). The effort is valiant but ultimately futile.
There are a few other options that further increase the difficulty of fetching and effectively using a session. For instance You could reissue session id's very frequently say reissue a session id if it is older then 1 minute even if you keep the user logged in he gets a new session id so a possible attacker has just 1 minute to do something with a highjacked session id.
Even if you apply all of these there is no guarantee that your session won't be highjacked one way or the other, you just make it incredibly hard to do so to the point of being impractical, but make no mistake making it 100% secure will be impossible.
There are loads of other security features you need to consider at server level like execution isolation, data isolation etc. This is a very large discussion. Security is not something you apply to a system it must be how the system is built from ground up!
Make sure you're absolutely not vulnerable to XSS attacks. Everything below is useless if you are!
Apparently, you mix two things: LocalStorage and Cookies.
They are absolutely two different storage mechanisms:
Cookies are a string of data, that is sent with every single request sent to your server. Cookies are sent as HTTP headers and can be read using JavaScript if HttpOnly is not set.
LocalStorage, on the other hand, is a key/value storage mechanism that is offered by the browser. The data is stored there, locally on the browser, and it's not sent anywhere. The only way to access this is using JavaScript.
Now I will assume you use a token (maybe JWT?) to authenticate users.
If you store your token in LocalStorage, then just make sure when you send it along to your server, send it as an HTTP header, and you'll be all done, you won't be vulnerable to anything virtually. This kind of storage/authentication technique is very good for Single-page applications (VueJS, ReactJS, etc.)
However, if you use cookies to store the token, then there comes the problem: while token can not be stolen by other websites, it can be used by them. This is called Cross-Site Request Forgery. (CSRF)
This kind of an attack basically works by adding something like:
<img src="https://yourdomain.com/account/delete">
When your browser loads their page, it'll attempt to load the image, and it'll send the authentication cookie along, too, and eventually, it'll delete the user's account.
Now there is an awesome CSRF prevention cheat sheet that lists possible ways to get around that kind of attacks.
One really good way is to use Synchronizer token method. It basically works by generating a token server-side, and then adding it as a hidden field to a form you're trying to secure. Then when the form is submitted, you simply verify that token before applying changes. This technique works well for websites that use templating engines with simple forms. (not AJAX)
The HttpOnly flag adds more security to cookies, too.
You can use 2 Step Authentication via phone number or email. Steam is also a good example. Every time you log in from a new computer, either you'll have to mark it as a "Safe Computer" or verify using Phone Number/Email.
I've been trying to learn the inner workings of OAuth 2.0 in my own RESTful app, and I can't seem to find any good explanation of how my Javascript client handles the process.
At this point, I have the client (an Angular 2 SPA) ask the user for their username and password (running Django Rest Framework along with Django Oauth Toolkit). The client makes an AJAX post to the server (specifically to /o/token), and using the resource owner password credentials flow is authenticated and receives the response with the token.
Now, assuming I'm doing everything correctly up to this point, I'm unsure how to properly handle the token from that point forward.
At this point, I'm having my Angular app save the token in a variable and attach the authorization header (with the token) to the calls made to the API. This works as far as granting the correct permissions, but im having a hard time understanding how to maintain persistence of the header (so if the user navigates to a different page, the token is still callable). Initially I stored it in a cookie, but I have concerns with security.
So, first, am I understanding all this correctly? What kind of security concerns should I take into account here? And, of course, how can I save the token on the client?
Yes, you need to store access tokens as user session data because they should be persistent. For example if user leaves your site and then reopens he expects to see himself logged in.
It will be better if you make your sessions server-side: user-agent will store only session ID and all user data will be in your database. User don't need his access token, only your application does.
Instructions for implementation of server-side sessions for Django look pretty simple:
If you want to use a database-backed session, you need to add 'django.contrib.sessions' to your INSTALLED_APPS setting.
Once you have configured your installation, run manage.py migrate to install the single database table that stores session data.
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.
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.