I am developing a new distributed application. I already have some operational microservice and it works fine. I am now implementing authentication/authorization and I have serious doubts.
enter image description here
1.- First I authenticate with the JWT microservice and obtain a token. This token contains the claims that indicate which properties that user has access to.
2.- This token has an expiration of 3 days. So when I make a request to a microservice I attach the token.
3.- However, when the request reaches any microservice controllers, how do I confirm that the token is valid and the user has permisions for this controller function? or if the claims have changed since the token was generated ?
Is it necessary to make another request to the JWT microservice to validate it?
Is there a more efficient way to validate each user's permissions in microservice controllers. I would like to not have to send another request to the JWT microservice again.
I have read that an API Gateway is sometimes implemented as an access point. If so, could the user access permissions be validated in the API Gateway? What technology is the most optimal (Camel, Spring Cloud)? To this, I add that we are deploying these microservices in Google Cloud Kubernetes (GKE).
enter image description here
If someone who has experience in microservices can enlighten me.
Thank you
There are two major approaches to token validation: local and rpc call.
Local is way more popular. This is the approach AWS, GCloud and Azure take. The token itself has all required information - who is the user, what are permissions. And the token is signed.
When this type of token is received on a service (or api gateway), the service can validate the token locally - by checking signature and expiration. Base on validated content of a token, the service decides what to do.
It is worth mentioning, that this approach does not allow token to be revoked. There are few workaround, but most solutions just rely on shorter lived token and issue a refresh token. (please, let me know if this is topic to talk more).
Having local validation also opens an interesting approach to limiting scope - when a system issues an access token, the token can have limited access - subset of whatever a user can do. This is nice feature to limit risks.
The other method is to call some internal service for token validation. This seems like easier to understand approach, but it scales purely.
One more thing to note: where token should be checked - on api gateway or on a service itself. Traditionally, access used to be checked on boundaries - api gateway in your case. These days, companies move to Zero Trust Architecture - which means access is verified on every service - there is no implicit trust.
Related
I'm trying to implement Google authentication for my app and the below is the workflow I'm trying to set up.
First, user will authenticate with Google and obtain an access token.
User will make requests with this token to backend services.
Backend services will check with Google to validate these token
Once validated, backend services will send information requested by client back to users
And I have a couple question around it:
Is this the correct way to implement it?
How to avoid check with Google for every single request between Backend and Frontend?
It's sort of the correct way. It depends on the details. If I understand correctly, you are in control of the front and backend (these are both your applications). If this is the case, then you would rather use Google services only to authenticate the user (so use an OpenID Connect flow to get an ID token to verify the user's identity). After that, you would have your backend either issue an access token or establish a session with your frontend. Then you wouldn't have to ask Google for the token's validity every time someone makes a request to your backend.
An access token that you get from Google, Facebook, etc. is meant to be used with their APIs. You could use it to authorize access to your own backend, but you then have to call Google on every request to verify the token. You are also tightly coupled to Google's details of the access token usage — what scopes are available, what data is returned with the token, expiration times, etc.
If the access token is a JWT, then you can verify it on your own in your backend. You don't have to call the issuer every time. But, if I remember correctly, Google issues opaque tokens, so this is not the way to go here.
To sum up. If you're in control of the front and back end, then authenticate with Google, then start a session between your applications. This will be simpler to maintain and also safer, as you wouldn't have to handle tokens in the browser.
I've been reading a fair bit on Microservices recently, and especially around AuthN and AuthZ. For the most part, this all makes a lot of sense, and I can see how it all should work.
For what I'm playing with, I going with delegated authorization - so I'm to be passing tokens around from client to service, and then passing the same token on from service to service. I also have an endpoint on the OAuth2 Service that will accept a token and return the details of the token - the User ID, the Start and End of the validity period, the scopes that the token is valid for, etc.
The problem that I'm running into here is - in order to correctly issue a token, there needs to be some communication with the User Service to ensure that the User that the token is for is actually valid. And in order to verify a Token, there needs to be some communication with the User Service to ensure that the User is still valid. And yet, in order to safely communicate with the User Service to get details about a User, a Token is needed that gives permission for this access.
I assume there is some standard practice on how to solve this circular dependency between the OAuth2 and User Service, but I've not seen any mention of it at all. Is this a common problem? Or have I just missed something obvious?
(Note - for now I'm only implementing Client Credentials Grant and Resource Owner Password Credentials Grant, since I'm only playing around to see how it all works and they're easier to call with cURL. I don't know that this makes any difference though)
Yeah, that's a bit of a chicken and egg problem. Not sure how much control you have over the authorization server, but one way of solving this issue is to secure the call to the user info service using client certificates.
Another is to combine the user info service and authorization server into one service and eliminate the need for the call all together.
I'm having a hard time choosing a decent/secure authentication strategy for a microservice architecture. The only SO post I found on the topic is this one: Single Sign-On in Microservice Architecture
My idea here is to have in each service (eg. authentication, messaging, notification, profile etc.) a unique reference to each user (quite logically then his user_id) and the possibility to get the current user's id if logged in.
From my researches, I see there are two possible strategies:
1. Shared architecture
In this strategy, the authentication app is one service among other. But each service must be able to make the conversion session_id => user_id so it must be dead simple. That's why I thought of Redis, that would store the key:value session_id:user_id.
2. Firewall architecture
In this strategy, session storage doesn't really matter, as it is only handled by the authenticating app. Then the user_id can be forwarded to other services. I thought of Rails + Devise (+ Redis or mem-cached, or cookie storage, etc.) but there are tons of possibilities. The only thing that matter is that Service X will never need to authenticate the user.
How do those two solutions compare in terms of:
security
robustness
scalability
ease of use
Or maybe you would suggest another solution I haven't mentioned in here?
I like the solution #1 better but haven't found much default implementation that would secure me in the fact that I'm going in the right direction.
Based on what I understand, a good way to resolve it is by using the OAuth 2 protocol (you can find a little more information about it on http://oauth.net/2/)
When your user logs into your application they will get a token and with this token they will be able to send to other services to identify them in the request.
Example of Chained Microservice Design
Resources:
http://presos.dsyer.com/decks/microservice-security.html
https://github.com/intridea/oauth2
https://spring.io/guides/tutorials/spring-security-and-angular-js/
Short answer : Use Oauth2.0 kind token based authentication, which can be used in any type of applications like a webapp or mobile app. The sequence of steps involved for a web application would be then to
authenticate against ID provider
keep the access token in cookie
access the pages in webapp
call the services
Diagram below depicts the components which would be needed. Such an architecture separating the web and data apis will give a good scalability, resilience and stability
You can avoid storing session info in the backend by using JWT tokens.
Here's how it could look like using OAuth 2.0 & OpenID Connect. I'm also adding username & password login to the answer as I assume most people add it as a login option too.
Here are the suggested components of the solution:
Account-service: a microservice responsible for user creation & authentication. can have endpoints for Google, Facebook and/or regular username & password authentication endpoints - login, register.
On register - meaning via register endpoint or first google/fb login, we can store info about the user in the DB.
After the user successfully logs in using either of the options, on the server side we create a JWT token with relevant user data, like userID. To avoid tampering, we sign it using a token secret we define(that's a string).
This token should be returned as httpOnly cookie alongside the login response. It is recommended that it's https only too for security. This token would be the ID token, with regards to the OpenID connect specification.
Client side web application: receives the signed JWT as httpOnly cookie, which means this data is not accessible to javascript code, and is recommended from a security standpoint. When sending subsequent requests to the server or to other microservices, we attach the cookie to the request(in axios it would mean to use withCredentials: true).
Microservices that need to authenticate the user by the token:
These services verify the signature of the JWT token, and read it using the same secret provided to sign the token. then they can access the data stored on the token, like the userID, and fetch the DB for additional info about the user, or do whichever other logic. Note - this is not intended for use as authorization, but for authentication. for that, we have refresh token & access token, which are out of scope of the question.
I have recently created a detailed guide specifically about this subject, in case it helps someone: https://www.aspecto.io/blog/microservices-authentication-strategies-theory-to-practice/
One more architecture perspective is to use nuget-package (library) which actually do authentication/token validaton. Nuget-package will be consumed by each microservice.
One more benefit is that there is no code duplication.
you can use idenitty server 4 for authentication and authorisation purpose
you must use Firewall Architecture hence you have more control over secutiry , robustness ,scalability and ease of use
Suppose I have a front-end application that wants to fetch some data from a back-end service. (I do.) The service will need to verify that the end-user is authenticated, that it is authorized to use the service and possibly filter the returned data based on the user's privileges. In my case, both the front-end app and the back-end service relies on Azure ACS for authentication.
Ideally the front-end would like to act on the behalf of the authenticated user, which sounds like a good fit for using an ActAs token (as specified in WS-Trust). However, it turns out that ACS does not currently support ActAs.
A workaround could be to use the actual bearer token (the bootstrap token in the front-end app) to authenticate to the back-end service. It's not hard to do, but would it be a bad idea for some reason?
From your front-end app, you could certainly pass along the identity data of the end user by either sending the token as is or sending the attributes from it. Both have issues. For the former, if it's also encrypted, the front- and back-ends will have to share the private key needed to decrypt it; they will also have to share audience restrictions, etc. in order for the back-end to consider the token valid for it. In other words, the front- and back-ends will be ONE relying party, not two. Might not be a problem, but be aware. In the latter case, you end up sending user data in a proprietay way which could increase integration and maintenance costs over time. In both cases, you can authenticate the front-end app to the back-end using some other type of credential, e.g., a certificate used at the transport level and, thus, forming a trusted subsystem between them.
One thing that I would suggest you consider instead is OAuth 2. From this blog post, it seems to me that ACS supports it (though I don't have any first hand experience w/ it). The truely wonderful thing about OAuth 2 is that it bakes delegation in, and is NO WHERE near as complex as ActAs in WS-Trust. The net result is the same, i.e., the back-end service will have info about the calling service and the end user, but the amount of effort to get it setup in incomparable. The tokens will still be bearer tokens, but you can mitigate that to a degree by using SSL. Beyond SSL, you can put some additional measures in place, but the best, IMO, would be if Microsoft did something in ACS like Google has done w/ their Access Tokens for service accounts which uses asymmetric keys that are chained up to a PKI. (BTW, for all I know, Microsoft may have already done something like that; if so, you're set.)
Anyway, HTH!
So I've been banging my head against the wall for the past couple days trying to understand how WCF's security architecture worked. I have a goal in mind and I'm not sure that I'm going in the right direction.
The System
We use a combination of Active Directory and databases to manage our authentication and authorization. Client applications typically use their Windows credentials to authenticate and the applications checks against database tables to see if those users are allowed to authenticate and then if they are authorized to use the resources they are requesting. The current setup has each client directly communicating with the database to do these checks.
The Goal
We want to use a Security Token Service to authenticate the client and provide "high level" authorizations for top level resources. The services that provide data or perform actions would operate if the supplied SecurityToken was valid. Additionally, the token, if it did not contain a particular right, would query the token service to see if the user did have rights that were not loaded when the token was initially created. (We have over 300 rights in our database, and that could lead to rather hefty tokens for users with many rights)
What I Don't Understand
1) I understand the token creation process, but I'm a little lost on how the client gets, stores and sends the token to the services it intends to use. Does each "worker" service require a unique token (i.e. call to CalculatorService requires one version of the token and the SaveResultService require a new token to be generated?) Can I manually request, save and send tokens?
2) On the "worker" service side, what is the process by which the token is verified? Does my "worker" service have to contact the Token Service for verification of the token? Or does it just read the token and assume, if it is properly signed, that the token is genuine and operate from that perspective?
3) Is it possible to encrypt my tokens manually and store them on the client side for use while they are valid (thus avoiding authentication attempts on every service call) and so that a web client can save the token between page loads and reuse it on successive calls?
Thanks for helping with my lack of understanding
You should go through the samples for Windows Identity foundation - It providers the classes and implementations required to wrap claims that you can use or query for auth and authz.
http://msdn.microsoft.com/en-us/library/ee517291.aspx
What you are looking for is a durable token cache. - Tokens have lifetimes and usually require renewal and WIF does the renewal under the hood for most scenarios.
You can manually request and attach tokens and pool the proxies using WIF.