Background
I am attempting to implement token authentication with my web application using JSON Web tokens.
There are two things I am trying to maintain with whatever strategy I end up using: statelessness and security. However, from reading answers on this site and blog posts around the internet, there appears to be some folks who are convinced that these two properties are mutually exclusive.
There are some practical nuances that come into play when trying to maintain statelessness. I can think of the following list:
Invalidating compromised tokens on a per-user basis before their expiration date.
Allowing a user to log out of all of their "sessions" on all machines at once and having it take immediate effect.
Allowing a user to log out of the current "session" on their current machine and having it take immediate effect.
Making permission/role changes on a user record take immediate effect.
Current Strategy
If you utilize an "issued time" claim inside the JWT in conjunction with a "last modified" column in the database table representing user records, then I believe all of the points above can be handled gracefully.
When a web token comes in for authentication, you could query the database for the user record and:
if (token.issued_at < user.last_modified) then token_valid = false;
If you find out someone has compromised a user's account, then the user can change their password and the last_modified column can be updated, thus invalidating any previously issued tokens. This also takes care of the problem with permission/role changes not taking immediate effect.
Additionally, if the user requests an immediate log out of all devices then, you guessed it: update the last_modified column.
The final problem that this leaves is per-device log out. However, I believe this doesn't even require a trip to the server, let alone a trip to the database. Couldn't the sign out action just trigger some client-side event listener to delete the secure cookie holding the JWT?
Problems
First of all, are there any security flaws that you see in the approach above? How about a usability issue that I am missing?
Once that question is resolved, I'm really not fond of having to query the database each time someone makes an API request to a secure end point, but this is the only strategy that I can think of. Does anyone have any better ideas?
You have made a very good analysis of how some common needs break the stateleness of JWT. I can only propose some improvements on your current strategy
Current strategy
The drawback I see is that always is required a query to the database. And trivial modifications on user data could change last_modified and invalidate tokens.
An alternative is to maintain a token blacklist. Usually is assigned an ID to each token, but I think you can use the last_modified. As operations revocation of tokens probably are rare, you could keep a light blacklist (even cached in memory) with just userId, and last_modified.
You only need to set an entry after updating critical data on user (password, permissions, etc) and currentTime - maxExpiryTime < last_login_date. The entry can be discarded when currentTime - maxExpiryTime > last_modified (no more non-expired tokens sent).
Could not sign out the action just trigger some client-side event listener to delete the cookie secure holding the JWT?
If you are in the same browser with several open tabs, you can use the localStorage events to sync info between tabs to build a logout mechanism (or login / user changed). If you mean different browsers or devices, then a you would need to send some way of event from server to client. But it means maintain an active channel, for example a WebSocket, or sending a push message to a native mobile app
Are there any security flaws that you 'see in the above approach?
If you are using a cookie, note you need to set an additional protection against CSRF attacks. Also if you do not need to access cookie from client side, mark it as HttpOnly
How about a usability issue that i am missing?
You need to deal also with rotating tokens when the are close to expire.
Related
I'm new to web development, and coming from the world of java and android I have a few questions. (I'm using asp.net).
Let's assume I have a simple webpage with a label showing a number and a button. When any user presses the button, the number gets incremented automatically for all the users viewing the site, even if they do not refresh the page. Would I use sessions to achieve this or there another concept I should look into?
I have 2 types of counters which I store in a mysql table with the following schema.
Counter_ID Increment_Value
Each counter is active for a set amount of time and only one instance of a counter can be active at one point in time. After this time, the counter is reset to 0 and a new instance of the counter is created. I store all the instances which are active as well as past instances in a table with this schema.
Instance_ID Counter_ID Counter_Value Status(Active/Complete) Time_Remaining
When a user opens a page dedicated to one of the two counter types, the information about the current running instance of that counter needs to be loaded. Would I just execute a SQL query to achieve this and read the information for active counters every time the counter page is loaded or is there a way in which I can store this information on the site so that the site "knows" which instance is currently active and does not require an SQL query for each request (using a global variable concept) ? Obviously, the situations described above are just simplified examples which I use to explain my issue.
You can use ApplicationState to cache global values that are not user-specific. In your first example, since the number is incremented for all users you can transactionally store it in the database whenever it is incremented, and also cache it in ApplicationState so that it can be read quickly when rendering pages on the server. You will have to be careful to ensure you are handling concurrency properly so that each time the number is incremented the Database AND the cache are updated atomically.
It's a little unclear from your question, but if your requirement is to also publish changes to the number in real-time to all users who are currently using your website you will need to look at real-time techniques. Websockets are good for this (if available on the server and client browser). Specifically, on the .NET platform SignalR is a great way to implement real-time communication from server to client and with graceful fall-back in case WebSockets are not supported.
Just to be clear, you would not use Session storage for this scenario (unless I have misinterpreted your question). Session is per-user and should typically not affect other users in the system. Your example is all about global values so Session is not the correct choice in this case.
For your second example, using ApplicationState and transactional DB commits you should be able to cache which counter is currently active and switch them around at will provided you lock all your resources while you perform the switch between them.
Hopefully that's enough information to get you heading in the right direction.
I need to architect a database and service, I have resource that I need to deliver to the users. And the delivery takes some time or requires user to do some more job.
These are the tables I store information into.
Table - Description
_______________________
R - to store resources
RESERVE - to reserve requested resources
HACK - to track some requests that couldn`t be made with my client application (statistics)
FAIL - to track requests that can`t be resolved, but the user isn't guilty (statistics)
SUCCESS - to track successfully delivery (statistics)
The first step when a user requests resouce
IF (condition1 is true - user have the right to request resource) THEN
IF (i've successfully RESERVE-d resource and commited the transaction) THEN
nothing to do more
ELSE
save request into FAIL
ELSE
save request into HACK
Then the second step
IF (condition2 is true - user done his job and requests the reserved resource) THEN
IF (the resource delivered successfully) THEN
save request into SUCCESS
ELSE
save request into FAIL
depending on application logic move resource from RESERVE to R or not
ELSE
save request into HACK, contact to the user,
if this is really a hacker move resource from RESERVE to R
This is how I think to implement the system. I've stored transactions into the procedures. But the main application logic, where I decide which procedure to call are done in the application/service layer.
Am I on a right way, is such code division between the db and the service layers normal? Your experienced opinions are very important.
Clarifying and answering to RecentCoin's questions.
The difference between the HACK and FAIL tables are that I store more information in the HACK table, like user IP and XFF. I`m not going to penalize each user that appeared in that table. There can be 2 reasons that a user(request) is tracked as a hack. The first is that I have a bug (mainly in the client app) and this will help me to fix them. The second is that someone does manually requests, and tries to bypass the rules. If he tries 'harder' I'll be able to take some precautions.
The separation of the reserve and the success tables has these reasons.
2.1. I use reserve table in some transactions and queries without using the success table, so I can lock them separately.
2.2. The data stored in success will not slow down my queries, wile I'm querying the reserve table.
2.3. The success table is kind of a log for statistics, that I can delete or move to other database for future analyse.
2.4. I delete the rows from the reserve after I move them to the success table. So I can evaluate approximately the max rows count in that table, because I have max limit for reservations for each user.
The points 2.3 and 2.4 could be achieved too by keeping in one table.
So are the reasons 2.1 and 2.2 enough good to keep the data separately?
The resource "delivered successfully" mean that the admin and the service are done everything they could do successfully, if they couldn't then the reservation fails
4 and 6. The restrictions and right are simple, they are like city and country restrictions, The users are 'flat', don't have any roles or hierarchy.
I have some tables to store users and their information. I don't have LDAP or AD.
You're going in the right direction, but there are some other things that need to be more clearly thought out.
You're going to have to define what constitutes a "hack" vs a "fail". Especially with new systems, users get confused and it's pretty easy for them to make honest mistakes. This seems like something you want to penalize them for in some fashion so I'd be extremely careful with this.
You will want to consider having "reserve" and "success" be equivalent. Why store the same record twice? You should have a really compelling reason do that.
You will need to define "delivered successfully" since that could be anything from an entry in a calendar to getting more pens and post notes.
You will want to define your resources as well as which user(s) have rights to them. For example, you may have a conference room that only managers are allowed to book, but you might want to include the managers' administrative assistants in that list since they would be booking the room for the manager(s).
Do you have a database of users? LDAP or Active Directory or will you need to create all of that yourself? If you do have LDAP or AD, can use something like SAML?
6.You are going to want to consider how you want to assign those rights. Will they be group based where group membership confers the rights to reserve, request, or use a given thing? For example, you may only want architects printing to the large format printer.
I am trying to implement a 'remember me' system with cookies that will remember a user across browsers meaning that if a user logs into a website using browser A and checks 'remember me', and then logs into browser B using 'remember me', he will continue to be automatically logged in regardless of which browser he uses. (checking 'remember me' in browser B will not break his persistent login in browser A).
To do this, I set up my database so that multiple keys can be stored alongside a user id. When a user logs onto my website, the cookie's value is checked. If that value is found in the database, the user is assigned a new cookie and that cookie key entry in the database is updated to match. Other keys are left alone so that other browsers' login persistence will not be affected. When a user logs out manually, the cookie is checked, the corresponding entry in the database is deleted, and then the cookie is deleted.
The problem comes up when a user manually deletes his cookie. If the user does this, I have no way of deleting the corresponding entry in the database. It will simply become a permanent entry in my database. This was not a problem when I was not trying to support cross-browser 'remember me', but has become a problem by allowing multiple cookie keys to be stored.
Is there any way that I can fix / avoid this?
There is a ton of information out there on persistent logins, but persistent logins across browsers never seems to be covered, so any help would be great. (Also feel free to critique my approach and any security issues. It seemed way more secure when I was only allowing one 'remember me' per user, but persistent log ins across browsers seems like functionality that users would want).
I am using MySQL and PHP.
I agree with #llion's suggestion of setting an expiry on the cookies, in which case you can schedule a process to clear out expired cookies from the dB. However, you can make this appear to the user almost as though the cookies are indefinitely persistent by extending their life whenever you see them.
For the benefit of any other readers interested in this question, I really hope that you are only storing hashes of the cookie in your dB.
I would suggest going with a "remember me (long enough)" solution. Set an expiry on the sessions but make it a lengthy one. Depending on how often you would expect users to login this could be anything from 8 hours to a week to a year plus. Each time they visit with a valid cookie you update the expiry behind the scenes and it appears persistent. If they delete cookies then eventually their session will be removed.
(If you're not actually using sessions, which it doesn't sound like you are, you'd need to add some maintenance coding around this. Probably best to learn about sessions instead of reinventing the wheel.)
To answer your question clearly:
There is no way for you to know of rogue remember_me tokens on the wild, the only real solution will be to be make your remember_me tokens last only a couple of weeks, then cron-job or daemon kill them.
This fixes your DB overcrowding which seems to be the use case of your request.
Please take a note you are facing a reality problem, where there is no way you can guess when a user has deleted the cookie, no backprocess is fired from the browser or other method, so the only approach will be to kill them regularly if not used, and refresh the expiration date once used.
The way you describe your system is more secure, (if done right) that long live php sessions, so i suggest you keep your current approach, secure it with series+tokens, and kill the unused for a couple of weeks long_live tokens.
Hope that helps you.
ummm, what happens if he is on another machine and uses a browser, same login? it's sure to happen. in our house I do this all the time. I have 3 boxes downstairs and my mother has 2 machines upstairs.
maybe you can guarantee a session is unique using microtime and the UA string from navigatior.userAgent
but you can't get the computername. but you could possibly get their IP address through the JS api. http://www.w3.org/TR/2010/WD-system-info-api-20100202/#network but using this might trigger some sort of warning dialog in the browser. nope. doesn't work.
java can get the ip.
I am just beginning to start learning web application development, using python. I am coming across the terms 'cookies' and 'sessions'. I understand cookies in that they store some info in a key value pair on the browser. But I have a little confusion regarding sessions, in a session too we store data in a cookie on the user's browser.
For example - I login using username='rasmus' and password='default'. In such a case the data will be posted to the server which is supposed to check and log me in if authenticated. However during the entire process the server also generates a session ID which will be stored in a cookie on my browser. Now the server also stores this session ID in its file system or datastore.
But based on just the session ID, how would it be able to know my username during my subsequent traversal through the site? Does it store the data on the server as a dict where the key would be a session ID and details like username, email etc. be the values?
I am getting quite confused here. Need help.
Because HTTP is stateless, in order to associate a request to any other request, you need a way to store user data between HTTP requests.
Cookies or URL parameters ( for ex. like http://example.com/myPage?asd=lol&boo=no ) are both suitable ways to transport data between 2 or more request.
However they are not good in case you don't want that data to be readable/editable on client side.
The solution is to store that data server side, give it an "id", and let the client only know (and pass back at every http request) that id. There you go, sessions implemented. Or you can use the client as a convenient remote storage, but you would encrypt the data and keep the secret server-side.
Of course there are other aspects to consider, like you don't want people to hijack other's sessions, you want sessions to not last forever but to expire, and so on.
In your specific example, the user id (could be username or another unique ID in your user database) is stored in the session data, server-side, after successful identification. Then for every HTTP request you get from the client, the session id (given by the client) will point you to the correct session data (stored by the server) that contains the authenticated user id - that way your code will know what user it is talking to.
Explanation via Pictures:
You can think of a session kinda like a library ID card. Everytime you go to a library, then you you show them your ID card which was issued by that particular library.
Simple Explanation by analogy
Imagine you are in a bank, trying to get some money out of your account. But it's dark; the bank is pitch black: there's no light. You are surrounded by another 20 people. They all look the same. And everybody has the same voice. And everyone is a potential bad guy. In other words, HTTP is stateless.
This bank is a funny type of bank - for the sake of argument here's how things work:
you talk to your teller and make a request to withdraw money, and then
you have to wait briefly on the sofa, and 20 minutes later
you collect your money from the teller.
But how will the teller tell you apart from everyone else?
The teller can't see or readily recognise you, remember, because the lights are all out.
What if your teller gives your $10,000 withdrawal to someone else - the wrong person?! It's absolutely vital that the teller can recognise you as the one who made the withdrawal, so that you can get the money (or resource) that you asked for.
Solution:
When you first appear to the teller, he or she tells you something in secret:
"When ever you are talking to me," says the teller, "you should first identify yourself as GNASHEU329 - that way I know it's you".
Nobody else knows the secret passcode.
Example of How I Withdrew Cash:
So I decide to go to and chill out for 20 minutes and then later I go to the teller and say "I'd like to collect my withdrawal"
The teller asks me: "who are you??!"
"It's me, Mr. George Banks!"
"Prove it!"
And then I tell them my passcode: GNASHEU329
"Certainly Mr. Banks!"
That basically is how a session works. It allows one to be uniquely identified in a sea of millions of people. You need to identify yourself every time you deal with the teller.
Difference between Sessions and Cookies
Sessions: You can think of sessions as the temporary passcode in the above example. Once the bank (i.e. server) sees the passcode - they will be able to identify who you are, what you want etc.
Cookie: You can think of a cookie as simply plastic card upon which information is printed on. You can store anything on that card, like:
name / age / sex / marital status
passcodes
Security Concerns with Cookies
The bank can write information onto your card - and so can you. But this can be dangerous:
name: Ben Koshy
sex: male
bank balance: $1.99.
If I wanna be sneaky, I could edit my ID card:
name: Ben Koshy
sex: male
bank balance: $1 billion bucks. <------ new line
Hooray! I could print more money than Yellen and Powell combined. This presents a security risk: it is for this reason that banks "encrypt" information on cookies, so that if you tampered with it, the bank would know. As a general rule you should never put anything compromising, that can be tampered into a cookie - the bank balance should be stored on the server, where nobody can directly tamper with it.
In this case, Powell decided to tamper with bank balance in his cookie. The bank can now invalidate his session:
name: Jerome Powell
session: tampering with bank balance, session invalid. log him out immediately. And fire him too.
"Session" is the term used to refer to a user's time browsing a web site. It's meant to represent the time between their first arrival at a page in the site until the time they stop using the site. In practice, it's impossible to know when the user is done with the site. In most servers there's a timeout that automatically ends a session unless another page is requested by the same user.
The first time a user connects some kind of session ID is created (how it's done depends on the web server software and the type of authentication/login you're using on the site).
Like cookies, this usually doesn't get sent in the URL anymore because it's a security problem. Instead it's stored along with a bunch of other stuff that collectively is also referred to as the session. Session variables are like cookies - they're name-value pairs sent along with a request for a page, and returned with the page from the server - but their names are defined in a web standard.
Some session variables are passed as HTTP headers. They're passed back and forth behind the scenes of every page browse so they don't show up in the browser and tell everybody something that may be private. Among them are the USER_AGENT, or type of browser requesting the page, the REFERRER or the page that linked to the page being requested, etc. Some web server software adds their own headers or transfer additional session data specific to the server software. But the standard ones are pretty well documented.
Hope that helps.
HTTP is stateless connection protocol, that is, the server cannot differentiate between different connections of different users.
Hence comes cookie, once a client connects first time to a server, the server generates a new session id, which later will be sent to the client as cookie value. And from now on, this session id will identify that client connection, because within each HTTP request it will see the appropriate session id inside cookies.
Now for each session id, the server keeps some data structure, which enables him to store data specific to user, this data structure you can abstractly call session.
Think of HTTP as a person(A) who has SHORT TERM MEMORY LOSS and forgets every person as soon as that person goes out of sight.
Now, to remember different persons, A takes a photo of that person and keeps it. Each Person's pic has an ID number. When that person comes again in sight, that person tells it's ID number to A and A finds their picture by ID number.
And voila !!, A knows who is that person.
Same is with HTTP. It is suffering from SHORT TERM MEMORY LOSS. It uses Sessions to record everything you did while using a website, and then, when you come again, it identifies you with the help of Cookies(Cookie is like a token).
Picture is the Session here, and ID is the Cookie here.
Session is broad technical term which can be used to refer to a state which is stored either on server side using in-memory cache or on the client side using cookie, local storage or session storage.
There is nothing specific on the browser or server that is called session. Session is a kind of data which represents a user session on web. And that data can be stored on server or client.
And how it stored and shared is another topic. But the brief is when a user is logged in, the server creates a session data and generates a session ID. The session Id is sent back to user in custom header or set-cookie header which takes care of automatically storing it on user's browser. And then when next time the user revisits, the session ID is sent along the request and server check if there is existing session by that ID and processes accordingly.
You can store whatever you want in an session but the the main purpose is to remember the the user (browser) who have previously visit your site whether it's about login, shopping cart, or other activities.
And that's why it also important to protect the session ID from being intercepted by a hacker who will use it to identify himself as an another user.
By reading about Cookie, you will get the idea of session: (https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
Excerpt from MDN:
Cookies are mainly used for three purposes:
Session management
Logins, shopping carts, game scores, or anything else the server should remember
Personalization
User preferences, themes, and other settings
Tracking
Recording and analyzing user behavior
I have a simple REST JSON API for other websites/apps to access some of my website's database (through a PHP gateway). Basically the service works like this: call example.com/fruit/orange, server returns JSON information about the orange. Here is the problem: I only want websites I permit to access this service. With a simple API key system, any website could quickly attain a key by copying the key from an authorized website's (potentially) client side code. I have looked at OAuth, but it seems a little complicated for what I am doing. Solutions?
You should use OAuth.
There are actually two OAuth specifications, the 3-legged version and the 2-legged version. The 3-legged version is the one that gets most of the attention, and it's not the one you want to use.
The good news is that the 2-legged version does exactly what you want, it allows an application to grant access to another via either a shared secret key (very similar to Amazon's Web Service model, you will use the HMAC-SHA1 signing method) or via a public/private key system (use signing method: RSA-SHA1). The bad news, is that it's not nearly as well supported yet as the 3-legged version yet, so you may have to do a bit more work than you otherwise might have to right now.
Basically, 2-legged OAuth just specifies a way to "sign" (compute a hash over) several fields which include the current date, a random number called "nonce," and the parameters of your request. This makes it very hard to impersonate requests to your web service.
OAuth is slowly but surely becoming an accepted standard for this kind of thing -- you'll be best off in the long run if you embrace it because people can then leverage the various libraries available for doing that.
It's more elaborate than you would initially want to get into - but the good news is that a lot of people have spent a lot of time on it so you know you haven't forgotten anything. A great example is that very recently Twitter found a gap in the OAuth security which the community is currently working on closing. If you'd invented your own system, you're having to figure out all this stuff on your own.
Good luck!
Chris
OAuth is not the solution here.
OAuth is when you have endusers and want 3rd party apps not to handle end user passwords. When to use OAuth:
http://blog.apigee.com/detail/when_to_use_oauth/
Go for simple api-key.
And take additional measures if there is a need for a more secure solution.
Here is some more info, http://blog.apigee.com/detail/do_you_need_api_keys_api_identity_vs._authorization/
If someone's client side code is compromised, they should get a new key. There's not much you can do if their code is exposed.
You can however, be more strict by requiring IP addresses of authorized servers to be registered in your system for the given key. This adds an extra step and may be overkill.
I'm not sure what you mean by using a "simple API key" but you should be using some kind of authentication that has private keys(known only to client and server), and then perform some kind of checksum algorithm on the data to ensure that the client is indeed who you think it is, and that the data has not been modified in transit. Amazon AWS is a great example of how to do this.
I think it may be a little strict to guarantee that code has not been compromised on your clients' side. I think it is reasonable to place responsibility on your clients for the security of their own data. Of course this assumes that an attacker can only mess up that client's account.
Perhaps you could keep a log of what ip requests are coming from for a particular account, and if a new ip comes along, flag the account, send an email to the client, and ask them to authorize that ip. I don't know maybe something like that could work.
Basically you have two options, either restrict access by IP or then have an API key, both options have their positive and negative sides.
Restriction by IP
This can be a handy way to restrict the access to you service. You can define exactly which 3rd party services will be allowed to access your service without enforcing them to implement any special authentication features. The problem with this method is however, that if the 3rd party service is written for example entirely in JavaScript, then the IP of the incoming request won't be the 3rd party service's server IP, but the user's IP, as the request is made by the user's browser and not the server. Using IP restriction will hence make it impossible to write client-driven applications and forces all the requests go through the server with proper access rights. Remember that IP addresses can also be spoofed.
API key
The advantage with API keys is that you do not have to maintain a list of known IPs, you do have to maintain a list of API keys, but it's easier to automatize their maintenance. Basically how this works is that you have two keys, for example a user id and a secret password. Each method request to your service should provide an authentication hash consisting of the request parameters, the user id and a hash of these values (where the secrect password is used as the hash salt). This way you can both authenticate and restrict access. The problem with this is, that once again, if the 3rd party service is written as client-driven (for example JavaScript or ActionScript), then anyone can parse out the user id and secret salt values from the code.
Basically, if you want to be sure that only the few services you've specifically defined will be allowed to access your service, then you only option is to use IP restriction and hence force them to route all requests via their servers. If you use an API key, you have no way to enforce this.
All of production of IP's security seems produces a giant bug to users before getting connected. Symbian 60s has the fullest capability to left an untraced, reliable and secure signal in the midst of multiple users(applying Opera Handler UI 6.5, Opera Mini v8 and 10) along with the coded UI's, +completely filled network set-up. Why restrict for other features when discoverable method of making faster link method is finally obtained. Keeping a more identified accounts, proper monitoring of that 'true account'-if they are on the track-compliance of paying bills and knowing if the users has an unexpired maintaining balance will create a more faster link of internet signal to popular/signatured mobile industry. Why making hard security features before getting them to the site, a visit to their accounts monthly may erase all of connectivity issues? All of the user of mobile should have no capability to 'get connected' if they have unpaid bills. Why not provide an 'ALL in One' -Registration/Application account, a programmed fixed with OS, (perhaps an e-mail account) instead with a 'monitoring capability' if they are paying or not (password issues concern-should be given to other department). And if 'not' turn-off their account exactly and their other link features. Each of them has their own interests to where to get hooked daily, if you'd locked/turn them off due to unpaid bills that may initiate them to re-subscribe and discipline them more to become a more responsible users and that may even expire an account if not maintained. Monthly monitoring or accessing of an identified 'true account' with collaboration to the network provider produces higher privacy instead of always asking for users 'name' and 'password', 'location', 'permissions' to view their data services. IP's marked already their first identity or 'finding the location of the users' so, it's seems unnessary to place it on browsers pre-searches, why not use 'Obtaining data' or 'Processing data.'