First off, I'll admit that I'm not even sure I'm going down the right path with the right questions. I've been thrown into the deep end as my company moves into GCP and am learning on the fly.
The situation I've got is a developer was able to use a token from another user to perform some work. What is really bad is the owner of the token left the company awhile ago. In admin.google.com I verified the user is suspended which shows me that our AD integration is working.
My assumption is the old user was issued a token somewhere with a very long and unacceptable time to live. Which leads me to two questions. The first is there a way I can find any and all tokens issued to this user? The second is if I'm going to be going down this rabbit hole, is there a way I can search for all long lived tokens?
I'm hoping for a gcloud solution that I can script out for formatting and any parsing I might need to do to get useable/human readable formatting without lots of extra inforamtion.
Related
I’m learning to code for one year now. I mainly learned how to deal with a rest API (Node/Express on back-end and Vue on front-end).
I get to the point where I want to develop the ideas I have for app.
For this, I first wanted to develop the backend to have a authentification process that I could use as a boilerplate for other project I would have.
But now I’m completely lost with Jsonwebtoken and how to exactly use it in order to make something secure as well as user-friendly.
So far I understand that a rest API should be stateless (I.e. nothing should be store server-side and should therefore not have DB calls -as for sessions- to grant access to data).
In this respect, I’ve noted different strategies :
Short-lived JWT : (+) this is very secure since you theoretically have to log in every time you want to access the server (-) very bad user experience
Long-lived JWT : (+) user-friendly (persistent login) (-) very insecure (no way to check if JWT was stolen)
Short-lived JWT with Long-lived Refresh Token…
That’s where I get confused…
From every articles/tutorials I’ve read, the refresh token should be linked somehow with a DB (e.g. to store the refresh token key or the blacklisted token…). I’ve also seen a tutorial that partly linked the secret key (to verify the token) with the hashed password stored in the DB. This is kind of smart since previous token will automatically be considered as invalid as of the moment the user changes his password… But this once again mean a DB call…
My point is that I’m coming to the conclusion that
(1) there’s no perfect way to handle authentification process in secure and user-friendly way…
(2) DB calls cannot be avoided to have something a bit secure...
And considering that conclusion, I definitely can’t understand the use of refresh token…
If refresh tokens required DB calls, you could get to the same result with only one main token…
You could for instance store a JWT ID in the token and in the DB… If those two id match upon validation of the token, you issue a new token with a new id that overwrites the previous one… Now if you use an old one, it will never be validated… Then, since you have called the DB to validate the token (most certainly the USER table), you could check in the sametime if, for example, the user is an admin or not (no need to store it in the JWT)… Finally, you could use the « hashed password » trick described above to enhance security…
So… What am I missing ? What is the best strategy ?
I’ll be happy to have your comments on this (or a link to a very good article - I’ve a lot of these though…)
Thank you very much for your help
PS: and I’m not even talking about how to send the token to the server (with cookie but risk of CSRF attach or with header but subject to XSS attack if token is stored client-side)… In this respect I’ve seen multiple tutorial that use JWT through cookie with cerf key stored client side as well as inside the jet => both should be send.
PS2: I hope I'm clear since I'm french-speaking native :-)
So you have asked quite a few questions in this one question. It will be quite difficult for anyone to give a thoughtful answer here, but I shall try. Before that, full disclaimer, that I am the author of a new library called SuperTokens that I believe would provide you the best solution for session management. It's possible that you may have already read our blog: https://hackernoon.com/all-you-need-to-know-about-user-session-security-ee5245e6bdad. It's best if we can chat about this so that I can give you a full detailed explanation about everything you have asked (I would love to help out). Join our discord: https://discord.gg/zVcVeev
Now to answer your question(s):
You should always only use short lived JWTs
Doing a database call for authentication is not a problem, but as everything else, we try and optimise things, so doing fewer db calls, is better. If you go with JWT access tokens and Opaque Refresh tokens, then for most APIs, you do not need to do a db call. However, if you link the secret key of the JWT with the hashed password, then you would have to a db call for every API - which is OK, but I feel unnecessary since you are going to use short lived JWTs anyways (a few hours to a day max)
You mentioned token theft - this is a tricky issue, but according to RFC 6819, you can use the concept of rotating refresh token to detect theft. Of course, actually doing so can be tricky as you have to take care of many race conditions and network failure issues - see https://hackernoon.com/the-best-way-to-securely-manage-user-sessions-91f27eeef460
About why we need refresh tokens: Say you do not have a refresh token, then you would have just one token that you could treat as both, an access and a refresh token. You could still make it short lived (when it's an access token), and then after it expires, treat it as a refresh token - which also has some lifetime. The problem with this is that it's not very clean (point of expiring a token is that it is useless afterwards), and that you are exposing the refresh token over the network every single API call - reducing security. I know you can have HTTPS, but there are HTTPS MITM attacks as well - see the blog post, part 1.
In terms of storage, one neat trick could be to split the access token into two - one to store in secure, httponly cookie, and one to store in localstorage. For every API call, send both to the server (cookies will be sent automatically anyways), and then the server would combine the two and go about authenticating. This would prevent both, CSRF and XSS attacks on sessions!
Now, you could either implement this whole thing on your own, or then use our library that does all these things out of the box: https://github.com/supertokens/supertokens-node-mysql-ref-jwt.
To discuss this more, or any other questions you have, join our discord server.
PS: I know I used this for advertising my lib, but I hope I did answer your question. It is genuinely difficult to give a good explanation to your questions without having a conversation.
I'm making an angular app that has users log in, make progress, then they are awarded levels/experience points. I'm using a nodejs/express API and I want to be able to make a call from my app to award them exp. I'm using a JWT and server signing with a private key to auth requests, but realized that a user could just pull their token and give themselves experience. My question would be is there anyway to protect my route from that or is that a fundamental flaw in design?
I don't believe this is something you can do specifically with JWT. As commenters have already said, JWT just provides access rights for the given token. As you say yourself, it would be simple enough to just read the traffic and send their own requests to jack up their exp.
While your basic authentication/authorisation mechanism can't solve this, you can handle it in some other fashion within, for example, the request payload itself.
You could encrypt and/or sign your payloads - given that the app would need to know or receive key(s) to use, it's possible that with enough investigation that this is eventually found and duplicated as well. But it's another step someone would have to go through and replicate.
You could employ additional checks and measures - have your requests for [exp increase] be a two-step process; the server responds to the initial request with some minor task to be solved that is then attached to the follow-up request. Assuming the task is done properly, you can be reasonably sure that it came from your app as your app knows how to solve the problems issued (or someone with a serious lack of hobbies outside of deconstructing your entire application).
You could limit the amount of exp that should be reasonably achievable by your users. If you know that people should, at most, be able to gain xyz exp per minute/hour/day/etc, then by monitoring exp growth, you can flag and/or block additional gains past this point.
A little background: I am going to be constructing a webserver, likely the most up to date version of apache when I get around to it. It is going to be updated with sensory information from a makeshift security system I have.
As a counterpart, I am designing an app to go along with it, that will automatically contact the webserver and pull the sensory information about once every 1.5 minutes.
I want to have an authentication method so that the average Bob can't see this information, mostly due to the fact that there will be some command and control as part of the server as well.
The question: I feel like a simple username and password is the wrong way to go about this since it isn't dynamic and theoretically seeing the same credentials sent that frequent could be dangerous, so is there any other authentication method that could mitigate this?
The question pt. 2: Obviously I want an encrypted channel, will https stumble over itself if it tries to renegotiate every minute and a half?
I haven't begun this project yet much less chosen any language to write it in, meaning I am super open minded to suggestions, any help is greatly appreciated.
The question: I feel like a simple username and password is the wrong
way to go about this since it isn't dynamic and theoretically seeing
the same credentials sent that frequent could be dangerous, so is
there any other authentication method that could mitigate this?
You could use Google Sign-In to allow log on via a Google account.
Or you could implement two factor authentication with say Google Authenticator or via SMS to prove that the user logging in has more than one factor of authentication. These factors could be:
Something you know (e.g. password)
Something you have (e.g. phone that provides a One Time Password)
Edit: Having re-read your question - yes you are fine to authenticate with username and password (over HTTPS), however you should then store a session identifier client-side and simply send this in future rather than the username/password each time. This is more secure as it can be stored safely client-side, and if exposed the identifier can be easily revoked.
The question pt. 2: Obviously I want an encrypted channel, will https
stumble over itself if it tries to renegotiate every minute and a half?
Nope, this is what it is designed for. Browsers will keep open an HTTPS connection for a length of time. Additionally, they will use session resumption rather than executing a full HTTPS handshake in the case that a new connection needs to be established. Session resumption is much quicker than establishing a completely new session. See this article on the CloudFlare blog for more info.
I couldn't come up with anything on Google, but this is a question I've had in my mind for a while, so I figured I'd present it here.
Let's say you're designing a typical username/password login. You set up a form where the user enters their username and password and then clicks a button to log in. Now, let's say they typed the password wrong. Is it better to generically say the login failed, or is it acceptable to specifically inform the user that it was their password that was wrong?
My thinking is that telling them exactly what part of their credentials was wrong would make hacking attempts easier because a hacker could determine a username that is valid and then keep trying passwords for that username. If the error message is generic and doesn't say whether it was the username or the password that was wrong, then it becomes more difficult for them. Of course, ideally the system would be designed to make brute-force hacking infeasible.
When I'm trying to log in somewhere and the login fails, I find it somewhat frustrating when I am given a generic error message. If I don't remember what my username was exactly, and then on top of that I may have used a different password than normal, it makes it much more difficult for me to figure it out because I'm working with two variables and never know if I got one of the two right.
I'd appreciate any input on this. I'm leaning toward specific error messages for a system I'm designing because it's more informative and convenient for the user, but I can be convinced otherwise.
Thanks!
Depends on the nature of the site. If this is an online banking app then don't give anything away.
If it's simply a logon to a forum or comment then telling me that I used the wrong username/email/passwd will avoid a lot of frustration
I personally think telling the user that an account does not exist is bad practice. Take a look at the example of Google (or most other large provider of web services). The error message returned for a failed login with Gmail is this: http://support.google.com/accounts/bin/answer.py?hl=en&p=mail&ctx=ch_ServiceLoginAuth&answer=27444
Note that even if the username does not exist, the exact same error is returned. This prevents a potential attacker/spammer from mining email addresses by the difference between "User not found" and "Username/Password failed".
Reference: http://www.harezmi.com.tr/how-to-keep-hackers-informed-about-your-users/?lang=en
FranklyI do not see why you shouldn't tell the user what went wrong. Surly some will disagree with me, and if we potentially give an attacker valid usernames this will off course be used in SQL injection attacks and brute force attacks which might be a security risk. But I motivate my answer by these points.
First one is from your own question
Of course, ideally the system would be designed to make brute-force hacking infeasible.
This is really the key and if you have mechanisms in place such as only allowing a number of failed attempts for a username per hour, a limited failed attempts per IP-adress per hour, long passwords and so on, will drastically reduce an attackers chances to brute force a password even if they know a username. If they can only test 10 passwords per username, and 100 passwords in total each hour, it would take around 285 days to test each possible combination of a 6 character ASCII only password, and 1995 days with a 7 character one. I know that attackers can fake IP-adresses so this specific method isn't watertight on it's own but it is possibly to severely obstruct bruteforcing, which is my point.
The generic error message is bordering on Security by Obscurity. Chances are that an attacker already knows one or more username. I.e. they know a mail address and people often use the same username, they use timing (as pointed out by Jonathan Leffler) to determine if their usernames might be valid, some usernames are really common (admin and administrator for instance) and so on. If part of your security relies on the fact that the attacker shouldn't know/guess usernames you will be unprepared when they do.
Stored procedures will mitigate the risks of SQL-injection attacks and by using basic security measures (not using urls like domain.com/delete/user/username/ to do things and be vigilant with authorization ) an attacker can't really do much with the username other than try to bruteforce.
So basically I see the risk as really low and the benefits as quite high for the user. It also encourages you as a developer to not be lazy with security.
The primary reason to be vague is precisely to make it harder for the hacker to guess whether the user name or the password is wrong. Once they get a user name, they can start making guesses for the password based on the user name with depressing effectiveness.
So, for anything where there is a concern about hacking attempts (roughly, any system where you think a password is a good idea), don't let them know which is wrong - give the same message in the same elapsed time regardless of whether the user name or the password is wrong.
(The timing is important too; if the attacker can spot that a bad user name takes 3 ms to come back and a bad password takes 10 ms, then you've told them whether the user name or the password is wrong. Scale the times to suit your application - but if there's a difference, someone will automate a timing attack using the information, even if there is noise in the timing because of the internet.)
I would go for a generic error message ("Login failed with given email/password") and working password reset function (via email).
I want to create a portal website for log-in, news and user management. And another web site for a web app that the portal redirects to after login.
One of my goals is to be able to host the portal and web-app on different servers. The portal would transmit the user's id to the web-app, once the user had successfully logged in and been redirected to the web app. But I don't want people to be able to just bypass the login, or access other users accounts, by transmitting user ids straight to the web app.
My first thought is to transmit the user id encrypted as a post variable or query string value. Using some kind of public/private key scenario, and adding a DateTime stamp to key to make it vary everytime.
But I haven't done this kind of thing before, so I'm wondering if there aren't better ways to do this.
(I could potentially communicate via database, by having the portal store the user id with a key in a database and passing that key to the web app which uses it to get the user id from that database. But that seems crazy.)
Can anyone give a way to do this or advice? Or is this a bad idea all-together?
Thanks for your time.
Basically, you are asking for a single-sign-on solution. What you describe sounds a lot like SAML, although SAML is a bit more advanced ;-)
It depends on how secure you want this entire thing to be. Generating an encrypted token with embedded timestamp still leaves you open to spoofing - if somebody steals the token (i.e. through a network sniffing) he will be able to submit his own request with the stolen token. Depending on the time to live you will give your token this time can be limited, but a determined hacker will be able to do this. Besides you cannot make time to live to small - you will be rejecting valid requests.
Another approach is to generate "use once" tokens. This is 'bullet proof' in terms of spoofing, but it requires coordination among all the servers within the server farm servicing your app, so that if one of them processed the token the other ones would reject it.
To make it really secure for the failover scenarios, etc. it would require some additional steps, so it all boils down to how secure you need it to be and how much you want to invest in building it up
I suggest looking at SAML
PGP would work but it might get slow on a high-traffic site
One thing I've done in the past is used a shared secret method. Some token that only myself and the other website operator knows concatenated to something identifying the user (like their user name), then hash that with a checksum algorithm such as SHA256 (you can use MD5 or SHA1 which usually are more available but they are much easier to break)
The other end should do the same thing as above. Take the passed identifying information and checksum it. Compare that to the passed checksum, if they match the login is valid.
For added security you could also concat the date or some other rotating key. Helps to run SSL on both sides as well.
In general, the answer resides somewhere in SHA256 / MD5 / SHA1 plus shared secret based on human actually has to think. If there is money somewhere, we may assume there are no limits to what some persons will do - I ran with [ a person ] in High School for a few months to observe what those ilks will do in practice. After a few months, I learned not to be running with those kind. Tediously avoiding work, suddenly at 4 AM on Saturday Morning the level of effort and analytical functioning could only be described as "Expertise" ( note capitalization ) There has to be a solution else sites like Google and this one would not stand the chance of a dandelion in lightning bolt.
There is a study in the mathematical works of cryptography whereby an institution ( with reputable goals ) can issue information - digital cash - that can exist on the open wire but does not reveal any information. Who would break them? My experience with [ person ]
shows that it is a study in socialization, depends on who you want to run with. What's the defense against sniffers if the code is already available more easily just using a browser?
<form type="hidden" value="myreallysecretid">
vis a vis
<form type="hidden" value="weoi938389wiwdfu0789we394">
So which one is valuable against attack? Neither, if someone wants to snag some Snake Oil from you, maybe you get the 2:59 am phone call that begins: "I'm an investor, we sunk thousands into your website. I just got a call from our security pro ....." all you can do to prepare for that moment is use established, known tools like SHA - of which the 256 variety is the acknowledged "next thing" - and have trace controls such that the security pro can put in on insurance and bonding.
Let alone trying to find one who knows how those tools work, their first line of defense is not talking to you ... then they have their own literature - they will want you to use their tools.
Then you don't get to code anything.