Short: How to authenticate and authorize role-based users in a microservice architecture?
Long: Say that you have the architecture given below.
I am struggeling to see what would be the best practice solution for securing such an architecture.
When i search i get alot of different answers.
"Leave authentication to a thirdparty OAuth provider". This seems like adding a lot of overhead and complexity for a rather simple application, and it may not be desireable to delegate authentication and authorization to a third party.
"Use JWT". If I am correct, then the use of JWT token is not suitable for external use (like in a SPA).
"Use a combination of opaque tokens externally and JWT internally linked in a redis/memchache". This seems like the best solution for my given situation, but my problem here is the lack of actual references to libraries/code examples.
I would higly appriciate if someone had some references of actual implementations to what i am trying to accomplish which would be:
Authentication, role-based authorization, in a microservice architecture.
There is not enough information to suggest what exactly should you be doing with architecture wrt authentication and authorization but I can tell you one of the approach that I tend to rely on.
Follow OAuth, as it gives you quite a few option, you can start with your own IDM/IAM and can later connect via social platforms.
We started of with JWT and for most part it was just a signed token (some time later we moved to signed and encrypted tokens). We created one service responsible for handling authentication and creating the JWT token. (We started with Keycloak but later moved to own service as keycloak was lil bulky for our use case)
When you say external, I am not sure what you mean by that, if is just accessible to end user IMO we can live with just a signed token. Yes all the information is visible to the user, but that is all his info and some authorization related information.
If you are passing your token to someone outside your boundaries, to an actual external system, where you do not want to share use information you can think of encrypting it, but then there will quite a lot of things that you need to think from security perspective and therefore going for either a standard security platform or a third party provider (whom both of you can trust and who puts enough thought in securing it) can help you in the long run.
Using the combination of an opaque token and JWT may be an overkill, unless you have a very strong reason against it. IMO you keep it simple to start with, make use of JWT through out, if required encrypt it. All you need will be one more service to manage authentication and creating and signing a token and you should be good.
Related
I am a beginner/noob to authentication and network security. I am completing a big academic project and part of it requires authentication of users. I was going to use auth0, OAUTH2 and all these other fancy protocols. However, I ended up generating a JWT token, storing it using localStorage, then checking if it is not equal to null in order to grant the user access to routes that require login e.g. /home, /my_profile. Is this sufficient from a technical standpoint? What is the name of my protocol called?
If you're not sure then it's rather not a protocol or standard. You're just using a proprietary solution, which probably means that is much less safe than using standardised solutions (like OAuth or OpenID Connect).
Btw, storing access tokens in the local storage is considered unsafe. You can have a look at this article where we described the security problems of such a situation and how you can add a component which will remediate this.
I am developing a SPA application in angular and I have a lot of confusion about the correct way to implement authentication and authorization.
First of all, the application is a first-party app, which means that I am developing both the authorization server and resource servers.
The users that logs in the application must have full access to their resources on the platform.
So, I am doing it using OAuth2.0 and I have a couple of doubts about the domain of the protocol as well as security concerns.
First question:
The first question is if OAuth should be actually used to authorize first party applications. From my understanding this is a delegation protocol used to grant a third-party application controlled access to the user's resources on the platform, upon user consent. How does this fit in the context of a first-party app? In that case the app should get an access token with a scope that allows full access, right?
Second question:
Since this is a Single Page Application I couldn't store a secret on client side. So I am opting for using the authorization code grant with PKCE which would seem to be appropriate to manage this scenario. In this case I wouldn't ask for a refresh token but I would only retrieve the access token and using silent check to refresh it. I do not want to have refresh token insecurely stored on the browser. Is this PKCE really secure? The secret is generated dynamically but a attacker could eventually create a system using the same public client id and managing the PKCE properly, and finally get an access token that, in my case, gives full access to the users resources.
I could in the future allow controlled access to my app's resources to third party app, that's also one of the reason why I stick with OAuth.
The first question is if OAuth should be actually used to authorize first party applications. From my understanding this is a delegation protocol used to grant a third-party application controlled access to the user's resources on the platform, upon user consent. How does this fit in the context of a first-party app? In that case the app should get an access token with a scope that allows full access, right?
Yes, this makes sense to me. We skip the 'grant permissions' step for our own apps.
Is this PKCE really secure?
Yes, even without PKCE, authorization_code is pretty secure. Adding PKCE solves a a few potential security issues, but I would be somewhat inclined to call them edge cases. It is definitely right now the recommended choice.
The PKCE rfc has more information about the motivations behind PKCE:
https://www.rfc-editor.org/rfc/rfc7636#section-1
I actually came here looking for the answer to Question 1. My take is that in situations where we have no third party apps requiring access to our APIs we do not need OAuth. If we still need to use OAuth, then we can use Resource Owner Password Flow for first party apps. I have not seen any convincing answer anywhere confirming or rejecting this opinion but this is purely based on my understanding of OAuth.
Now, I am mainly writing this to answer Question 2. PKCE protocol is secure and attacker would not get token in this scenario. The reason is that the Authorization Server uses pre-registered "Redirect Uri" to send the token to. To be precise, the Auth Server would simply ask the browser to redirect user to "Redirect Uri appended with Access Token". Browsers do not allow javascript interception of Redirection requests. Therefore, an attacker would not be able to get hold of the token and the user will be redirected from attacker's site to yours at the end.
Is it possible to implement the Oauth2 flow in which , instead of a specific identity provider being used in the redirect, you instead ask the user to submit an email address, and then send an authorization code to that email address, and they click the link to get issued an access token?
In this scenario, how would one make use of a state parameter to prevent CSRF? And, are there other security implications to this design?
It's possible with a custom grant type (example). Translation: this will be a scheme that is proprietary to your clients and your authorization server. You're either going to have to write a lot of code yourself or rely on a commercial solution such as one linked above. Your clients will have to understand this flow...so you won't be able to grab any oAuth-compliant app and expect that it'll work with this scheme.
A better option is to NOT go through email and NOT require a user entry of an additional authentication factor. Instead, use one of the standard grant types with a well-defined threat model. Recommendation: authorization code grant type with PKCE extension. It takes care of CSRF and many other threat vectors. See oAuth Security Best Current Practice (BCP) for more details.
As an alternative, you can perform your email-based verification routine after the oAuth flow is done.
I have read a lot about OIDC and OAuth2, I know the id token is mainly used for the client to know who the user is and whether the user is still online currently.
Furthermore, Id token can prevent a class of impersonation attacks [You can find more details in this article].
But what if the id token is stolen? Can the attacker uses the id token to impersonate a user?
In our project, we just ensure https besides the OIDC. What else security consideration should I take to mitigate the impersonation attacks?
The goal or purpose of OIDC is not to be more secure than OAuth2, and this kind of comparison doesn't make sense. They solve different problems.
Let's start with OAuth2. In very short and somewhat simplified, OAuth2 solves the problem when a website holds data of a user, and that user wants to grant access to some of their data to another website. Say you have a Facebook account, but want to allow my application to access some of your data on Facebook, or for a more concrete example, you want to allow my awesomeapp.com app to post a link to your Facebook wall. For this, my website redirects you to Facebook, you log in, get an access token, and send that access token back to my website so that I can use it in your name to get what you allowed me to.
Note that there is one thing missing. I have no idea who you are. I just had an access token, with which I can do stuff, but I don't have identity info about you. Sure, this can be abused in different ways, the access token can hold your email address or whatever, but it's limited, the size matters, and there is no standard way.
At least not until OIDC comes in the picture. OIDC provides the identity element.
The purpose of the ID token is to provide identity info, to tell me claims about who you are. It may claim what your email address is, what security groups you are in, which company you work for, or anything else. Also it may be used to download more claims, in case they don't all fit in the actual token (see userinfo). These claims come from the Identity Provider, say Facebook, which my application then has to trust of course, i.e. I will believe whatever Facebook tells me about you.
This is all possible with pure OAuth2, but there is no standard, well known way to do so (or well, it is OIDC :) ). You could invent and implement something yourself, but these things are more complicated than they may first seem to be. That's why OIDC was invented, so you don't have to. But after all, OIDC is just a way to use OAuth2 to provide identity. In the end, it's just an extended OAuth2 if you like.
As for what security considerations you need to take into account - this part of your question is way too broad and can't be answered unfortunately. Security is a very complex topic.
I'm not really a security purist so my additions to Gabor's points are from a more practical viewpoint, as someone responsible for building well architected UIs and APIs:
An id token represents proof of authentication to a UI
An id token is NEVER used by APIs, which must use access tokens instead
An id token is the only type of token a UI should ever read, and it is mandated to have a JWT format
For Web UI logins an id token provides extra security, since it enables the UI to validate tokens and protect against some types of token substitution attack - so yes - OIDC is more secure
An id token is sometimes needed in order for logout to work
You should ALWAYS use a certified security library that does this type of work for you, rather than reading tokens directly in your own code.
I was thinking about security for my REST web Service API, and decided to take a look at others large services and how they do it. As an example I decided to study Twitter's OAuth. After reading beginners guide I'm a little be confused and shocked.
As I understood it's Service provider responsibility to authenticate user and to show User what kind of access consumer is demanding (for example it want's read only access to specific resource). But I saw service providers that doesn't inform user on what type of access consumer is demanding (and even now showing consumer's identity). The second part of problem is that consumer can show his own custom Provider Service Authentication form in IFrame, and just hide access details, they can just steal you password, or request unlimited access to you resources, they can do basically what ever they want, there are lot's of way to trick user.
As an example let's take a LinkedIn. They request your gmail username and password inside their own form, and you have no idea how they will use it. They can just steal it and store in their DB, they can OAuth with it to gmail (and they don't show gmail's page with information what type of access they request), they can do whatever they want with this information.
What I'm trying to say is not that OAuth communication protocol is not secure, but rather there are lot's of way to use it improperly to trick the user and get his credentials.
BTW there were some security flaws in OAuth protocol itself: (http://oauth.net/advisories/2009-1/) and I'm pretty sure there are more, but no one cares to find them.
I'm going to go with 'You didn't understand it.' (In your defense, very few people do.)
Let's be clear: The session fixation attack you're referring to affected OAuth 1.0, but was resolved in OAuth 1.0a, which became RFC 5849. There are no major implementors of OAuth 1.0 — the major implementors all either implemented OAuth 1.0a/RFC 5849 or they implemented one of the OAuth 2.0 drafts.
As for the username/password anti-pattern, OAuth 1.0a does not provide for a mechanism to exchange a username and password for an access token. OAuth 2.0 does, but only for the purposes of supporting installed applications. Keep in mind that an installed application could simply keylog (or similar) if it really wanted to. When it comes to security, all bets are off if an application is already running natively and unsandboxed on the client's machine. But this is actually a very different scenario than what you're talking about. Web applications in both OAuth 1.0a and OAuth 2.0 don't ever touch the username and password.
The flow for OAuth 1.0a goes like this: The application asks the provider for a request token, telling it all of the things it wants access to. The provider issues the temporary unauthorized token, at which point the client may send the user to the provider to authorize that token. The user logins in with their username and password on the provider's site and then either grants or denies access. The provider then redirects back with a verifier string that allows the site to upgrade to an authorized access token. All of these interactions are signed. If the signatures don't match on any of them, the provider will reject the request. And the user can revoke any token at any time, removing the client's ability to access their account.
There are a number of security considerations with the protocol, but if you actually read the list, it's essentially the same list of the security issues that affect almost every site on the internet. These security considerations are all very well known and very well understood. To my knowledge, there are currently no known exploitable attacks against providers that correctly address all of these security considerations.
Point being, you are much safer using OAuth 1.0a or OAuth 2.0 to authorize a third party than with any of the alternatives. If you don't feel comfortable with these, the solution is simple: Don't authorize third parties to access your account. There certainly are plenty of reasons why you might not want to do that.
It sounds like you are confused about what's not secure. As I understand it, the OAuth protocol itself, if implemented properly, is secure. It's just that it's easy to implement improperly, and users get confused because they don't really understand what they are doing.
For example, what LinkedIn is doing is all wrong. I would never give them my gmail account information in this way. In order for me to provide my gmail account information, I insist on seeing that my browser is using SSL with Google and so the root frame of the page comes from Google.
Then there is the matter of trusting Google to correctly tell me what access is being requested and by who. If I don't trust them to do this, I shouldn't be using OAuth.