Microservices Authentication best practices and security (OAuth 2.0 and OpenIdConnect) - security

There are several ways to build authentication in micro-services. However very popular is using JWT tokens and OAuth protocol together with OpenID Connect identity layer.
In this tutorial explaining how it can be achieved there is one tip:
Pass by reference when tokens have to leave your network, and then convert them to by-value tokens as they enters your space. Do this conversion in your API gateway.
However it's not clear to me what's reason behind it. I suspect it might be due to some security benefits (not to give client possibility to read any specific info). Because in the JWT token itself it might be info about roles/permission. But for this purpose token can also be encrypted.
Another reason might be that JWT token is too big and in order to don't carry this token every time such approach might be used. (or if JWT token is stored in cookie it has size limits).
I haven't seen any info that JWT token authentication is compromised and it's a bad practice to keep it on client (in browser).
On the other hand I see that Ping Identity is also using pass by reference approach. Can you help me understand the reasoning behind it?

They are both valid options and as always it's the exact scenario where you want to apply them that will dictate the most appropriate. As it's generally the case, each option will have its pros and cons and you already mentioned a few, so I'll try my best to add something new to the discussion.
The major difference is in the contents, by-value will contain the actual values while the reference is just a random sequence of bits. If you want to represent sensitive information in the token, this may tip the scale in favor of reference tokens.
It's true that if you use JWT you can encrypt them to ensure confidentiality, but this adds a significant layer of complexity and the support for JWT encryption in the available libraries is most likely not as good as the support for signing given that encryption does not have a similar widespread use.
Regarding the size, I don't think this should be a deciding factor. Yes, if you go with by-value tokens you need to keep them sufficiently small as to not cause significant overhead on the channel, but you should not pick one vs the other only because of this constraint.
One thing you did not mentioned, but I believe it's important is that reference tokens seem more suitable for situations where the authorization server and resource server belong to the same entity. It's true that there is already a standard to cover token introspection so that an external resource server can query information about a reference token in an interoperable way. However, it's still true that, when both actors are within the same security boundary, reference tokens should be easier to scale and implement.
The suggestion on the article it's also interesting, you get reduced overhead on the external network and no issues with information disclosure and then do the upgrade to by-value tokens in one central place meaning that all other services behind it may still gain from the simplicity of having the required information already within the token itself.
In summary, if information disclosure is an issue to you you'll probably go for reference tokens in order to not take the cost of JWT encryption; otherwise, you might as well make life simple for you and go with value tokens.

I believe the main benefit (which the article wanted to convey - apart from the information disclosure) of using reference token (Opaque tokens) over by-value (JWT) is the ability to control the Access tokens when it is distributed outside the network.
In other words, if we issue Access Tokens as JWTs outside the network then it is hard to revoke the access during emergency (when a user is deactived /terminated, lost mobile phones, etc ). But reference tokens can be easily revoked since it is a pointer within the AS boundaries.
A more detailed explanation on this is available here.

Related

Is it a good practice to fetch client user's data from database on every api call?

For authentication in my REST API, I am using JWTs, which only contain the client user's UUID.
To check if the user is not blocked or has rights to execute a specific endpoint, I fetch the user's data from a PostgreSQL database using the UUID of the JWT, and verify if the user is allowed to execute.
Is it a good practice to do a database operation for securing every API call?
Also thought about storing roles and rights in the JWTs but what if these roles and rights change in the database and the JWTs data becomes stale? Is there any solution to the stale data?
You have to check some data store for staleness with JWT.
If you conclude with performance tests and measurements that accessing a PostgreSQL DB for every request would be too slow, then you optimize that part. Maybe optimize your DB performance by changing the data structure or configuration. Or use a completely different database just for this purpose. Bad practice would be trying to optimize this prematurely.
Here's an article that talks about how to manually expire JWTs, it describes an example with using Redis:
An implementation would probably be, to store a so-called “blacklist” of all the tokens that are valid no more and have not expired yet. You can use a DB that has TTL option on documents which would be set to the amount of time left until the token is expired. Redis is a good option for this, that will allow fast in memory access to the list. Then, in a middleware of some kind that runs on every authorized request, you should check if provided token is in The Blacklist.
TL DR: No its not :-)
In general JWT's are not the most suitable solution for scenario you describe, you are already facing the first trouble of it now.
Because you better store stateless information in your JWT, otherwise you would be better of using other authentication solutions.
Conclusion
Stateless JWT tokens cannot be invalidated or updated, and will introduce either size issues or security issues depending on where you store them. Stateful JWT tokens are functionally the same as session cookies, but without the battle-tested and well-reviewed implementations or client support.
Unless you work on a Reddit-scale application, there's no reason to be using JWT tokens as a session mechanism. Just use sessions.
source: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
And some other related posts:
http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/
https://medium.com/#yuliaoletskaya/can-jwt-be-used-for-sessions-4164d124fe23
https://logrocket.com/blog/jwt-authentication-best-practices/
Most security consultants / auditors I spoke to also are very strong in there statements about JWT, they are widely overused and have a specific problem domain.
But if you really want/need to, I would follow #ekuusela's answer, especially given:
Bad practice would be trying to optimize this prematurely.

JWT - What is the best way to use jsonwebtoken ? I'm lost

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.

Are breaches of JWT-based servers more damaging?

UPDATE: I have concluded my research on this problem and posted a lengthy blog entry explaining my findings: The Unspoken Vulnerability of JWTs. I explain how the big push to use JWTs for local authentication is leaving out one crucial detail: that the signing key must be protected. I also explain that unless you're willing to go to great lengths to protect the keys, you're better off either delegating authentication via Oauth or using traditional session IDs.
I have seen much discussion of the security of JSON Web Tokens -- replay, revocation, data transparency, token-specified alg, token encryption, XSS, CSRF -- but I've not seen any assessment of the risk imposed by relying on a signing key.
If someone breaches a server and acquires a JWT signing key, it seems to me that this person could thereafter use the key to forge unexpired JWTs and secretly gain access. Of course, a server could look up each JWT on each request to confirm its validity, but servers use JWTs exactly so they don't have to do this. The server could confirm the IP address, but that also involves a lookup if the JWT is not to be trusted, and apparently doing this precludes reliable mobile access anyway.
Contrast this with a breach of a server based on session IDs. If this server is hashing passwords, the attacker would have to snag and use a session ID separately for each user before it expires. If the server were only storing hashes of the session IDs, the attacker would have to write to the server to ensure access. Regardless, it seems that the attacker is less advantaged.
I have found one architecture that uses JWTs without this disadvantage. A reverse proxy sits between untrusted clients externally and a backend collection of microservices internally, described here by Nordic APIs. A client acquires an opaque token from an authorization server and uses that token to communicate with the server app for all requests. For each request, the proxy translates the opaque token into a JWT and caches their association. The external world never provides JWTs, limiting the damage wrought by stealing keys (because the proxy goes to the authentication server to confirm the opaque tokens). However, this approach requires dereferencing each client token just as session IDs require per-request dereferencing, eliminating the benefit of JWTs for client requests. In this case, JWTs just allow services to pass user data among themselves without having to fully trust one another -- but I'm still trying to understand the value of the approach.
My concern appears to apply only to the use of JWTs as authentication tokens by untrusted clients. Yet JWTs are used by a number of high-profile APIs, including Google APIs. What am I missing? Maybe server breaches are rarely read-only? Are there ways to mitigate the risk?
I believe you're thinking about this the wrong way. Don't get me wrong, it's great you're considering security, however the way you're approaching it in regards to double checking things server-side, adding additional checks that defeat the objective of stateless sessions, etc, appear to be along a one way street towards the end of your own sanity.
To sum up the two standard approaches:
JWTs are sessionless state objects, MAC'd by a secret key held server side.
Traditional Session Identifiers are stored either in memory or in a database server-side, and as you say are often hashed to prevent sessions from being hijacked should this data be leaked.
You are also right that write access is often harder for an attacker to achieve. The reason is that database data is often extracted from a target system via a SQL injection exploit. This almost always provides read access to data, but it is harder to insert data using this technique, although not impossible (some exploits actually result in full root access of the target machine being achieved).
If you have a vulnerability that allows access to the key when using JWTs or one that allows database tables to be written to when using session identifiers, then it's game over - you are compromised because your user sessions can be hijacked.
So not more damaging necessarily, it all depends on the depth of the vulnerability.
Double check that the security of your JWT keys align with your risk appetite:
Where are they stored?
Who has access?
Where are backups stored?
Are different keys used in pre-production and production deployments of your app?
The ways to mitigate is as good practise dictates with any web app:
Regular security assessments and penetration testing.
Security code reviews.
Intrusion detection and prevention (IDS/IPS).
WAF.
These will help you evaluate where your real risks lie. It is pointless concentrating on one particular aspect of your application so much, because this will lead to the neglect of others, which may well be higher risk to your business model. JWTs aren't dangerous and have no more risk than other components of your system necessarily, however if you've chosen to use them you should make sure you're using them appropriately. Whether you are or not comes down to the particular context of your application and that is difficult to assess in a general sense, so I hope my answer guides you in the right direction.
When an attacker is able to get hold of the signing key in a JWT based system that means that he is able to get access to the server backend itself. In that case all hope is lost. In comparison to that, when the same attack succeeds in session based systems the attacker would be able to intercept username/password authentication requests to the backend, and/or generate sessions ids himself, and/or change the validation routines required to validate the session ids and/or modify the data to which the session id points. Any security mechanism used to mitigate this works as well for session systems as for JWT systems.

Node.js authentication without passport: are json web tokens reliable?

I'm using the MEAN stack and want to make sure certain routes have an authenticated user. I've been reading up on JSON web tokens. This seems reasonable.
Before I invest anymore time into it, I want to ask if anyone else uses this and if there are any major flaws they've noticed thus far. And are there any other popular alternatives excluding passport?
JSON web tokens have several flaws which, when dealt with properly, can make the approach quite useful for performing authorization:
A client still needs to transmit user credentials to a authentication server, which means using secure transmissions is paramount
If sensitive information is placed into the token, this information should be encrypted by the client and sent across a secure transmission
Depending on how your constructing the token and who your sharing it with, tokens should have a limited lifetime, preventing others from destructuring the token since it's generation and potentially sending falsified data to servers
There are definitely other approaches to cookie-based authentication other than passport, but I'm not aware of any that are as well integrated and popularized, though I'm sure you might find something more efficient. There are other examples of cookie-based schemes that exists, which you could implement, for instance the auto-login scheme from SO.
If you want to invest the time to learn how to implement JWT, it would definitely be worth the effort. If your trying to asses whether you need to use JWT, a good rule of thumb is asking yourself whether you will have multiple authentication servers, will you need to authorize clients accross several different domains and whether you need the clients to have stateless/ephemeral authorization tokens.

Implementing SCRAM - nonce validation and server/client keys

Technically two questions - but they are so heavily related I didn't want to split them up; but if the community feels I should, I will.
Following a recent question I am implementing SCRAM for a website login and web service API. Client environments will be .Net and Javascript (with Java likely in the future).
My first issue is basic: The protocol utilises a client and server key as key steps in the authentication process; and yet in order to be validated, both need to be known by both parties in advance since the protocol doesn't allow for exchange of these (to do so would result in a bit of a chicken and egg scenario). If you consider a Javascript client, for example, this means both keys are likely to be constants defined in the source - thus making them easy to fetch. So: why bother? Is it just to mitigate against 'Eve' where that 'Eve', for some reason, hasn't bothered to get the JS or client source code, which will necessarily be public!?
Secondly, like practically any other authentication mechanism it requires a client + server nonce.
Given that the authentication nonce, by definition, should never be used more than once (at least by the same user), this presumably means that a server must maintain a record of all nonce values used by all users forever. Unlike other data that we regularly archive off, such a table is only ever going to get bigger and queries against it likely to get slower and slower!
If that's correct, then it's technically unfeasible to implement this or almost any other authentication mechanism! Since I know that's plainly ridiculous; it must be common to define some additional scope that factors in a reasonable timescale as well.
As always with authentication and encryption; despite being a very experienced software developer I feel like I'm going back to school! What am I missing!?
both need to be known by both parties
in advance since the protocol doesn't
allow for exchange of these (to do so
would result in a bit of a chicken and
egg scenario).
Yes that's correct. Challenge response isn't a key-exchange protocol. It only norms, once client and server share a key, how to compute the same value from that key without transmitting in clear the key via network.
If you consider a Javascript client,
for example, this means both keys are
likely to be constants defined in the
source - thus making them easy to
fetch.
That's not a good idea. Alternatively client and server can agree on a key during a preliminary registration process.
Given that the authentication nonce,
by definition, should never be used
more than once (at least by the same
user), this presumably means that a
server must maintain a record of all
nonce values used by all users
forever.
NO. A new nonce should be generated for each new session using pseudo-random number generation. It's very improbable that you will get the same nonce twice, anyway It doesn't matter if a nonce it has already been used if the attacker don't know that .

Resources