I have a simple question; I'm building a microservices project, with an API Gateway in front of my services.
Actually , all my ms ( microservices ) have an internal domain: http://ms.mydomain.lan
MS are behind an Api Gateway, that handle authentication.
All ms API are not accessible to the external.
So, all the traffic pass throught the Api Gateway: https://api.mydomain.it.
This is the core of the problem.
During the auth in Api Gateway, I detect the user and create a TOKEN ( not really a jwt, a simple encoded string )
This token is sent to ms requests using headers. Each MS decode the token ( that is NOT A JWT ), get the user and handle permission etc etc...
All work well BUT ... my doubt is: should each microservice perform a "token validation" , or it is not necessary?
Actually, a microservice decode a simple string; I'm sure that ms are NOT accessible to the outside, so no one can create a fake token.
But ... is the right way to do this? I'm thinking to create a JWT so that each MS has to validate the token with an authService but ... why should I add this overhead? is really necessary? I have to add an extra call to a service that has to validate the token ... Or I could store jwt secret in an NFS location and let the ms to validate the token by himself ...
Which is the best way to proceed? Is the validation of token really necessary in each single microservice?
Thanks in advance.
The pattern you are using is good. The api gateway handles the authentication and transfers the request to the internal services. The ms trust the gateway and perform only the authorization.
Wether you use a JWT token for internal communication is up to you. A simple string should suffice if the ms can use it for authorization.
I use the same pattern when building microservices.
Related
I'm developing rest api in spring for my company. I need to secure it using google OAtuh2. Firstly I used jwt token validation. Frontend app obtains token_id andd pass it to backend resource server. I've read that I sholud use access tokens instead of id_tokens (is that right?). For using opaque tokens introspection I need to provide introspection uri. I can't find it. Does google auth server support token introspection?
Yes you should use access-tokens only to secure requests to resource-server(s). ID tokens are for clients to get user-info.
Using access-token introspection has serious performance impact compared to JWT decoding: resource-server must issue a query to authorization-server for each and every request it processes (when JWT validation can be done locally with authorization-server public key retrieved only once). I recomand you don't do that.
If you cannot configure authorization-server to add the claims you need to JWT access-tokens, you should consider using an authorization-server capable of identity federation in front of it. It is very common to do so when several etherogenous identity sources are used (Google + Facebook + Github + LinkedIn + corporate LDAP for instance), but it would work with a single one too. Keycloak for instance does that and allows you to put whatever you need in access-tokens.
In a context with the following services:
API Gateway/OIDC client: connect to an external OpenId Connect Provider (to get access, refresh and id tokens) and act as proxy to forward requests to other services with the access token (Authorization code flow)
Several resource servers, incoming requests are handled by the API Gateway and include the access token (for validation, using the keys exposed by the OIDC provider)
I am using the Spring Security 5.2 Oauth2 client/resource server libraries.
What will be the recommended secure way to make all the resource servers services aware of the user information (included in the API Token).
I am evaluating several options:
Include the id_token in the request sent to the services. Each
service can then validate the token (in a filter).
Make the API Gateway act as a token issuer to make a new enhanced token based.
The resources servers will have to validate the token received with
a new key exposed by the API Gateway/Token issuer. With this
solution a custom AuthenticationManager has to be implemented.
I think option 2 is the more secure and future proof, is there any downsides I should consider? Also there are maybe other alternatives.
You should be able to achieve your goals without issuing a second level of token or sending id tokens to APIs. A common gateway solution is as follows:
Open Id Connect Provider (OICP) issues tokens to the client and does all the deep stuff like auditing of tokens issued + UIs for managing them
Client sends access token to resource server via API Gateway
API Gateway validates the access token, which can involve an introspection call to the OICP
API Gateway can send the access token to the user info endpoint of the OICP to get user info, then forward this to resource servers - perhaps via headers
API Gateway can be configured to cache claims (token + user info details) for subsequent calls with the same access token
Resource servers sometimes run in a locked down Virtual Private Cloud and don't need to revalidate the access token (if you are sure this is safe)
AWS API Gateway works like this when calling lambda functions. I actually like the pattern in terms of extensibility and it can also be used in standalone APIs.
My write up may give you some ideas, along with some sample authorizer code and a class that does the OAuth work.
I am planning to change the ASP.NET Web API 2.0 which includes Authentication and Authorization and all the services into Microservices architecture.
My Question if I create a central microservice to handle authentication and authorization. How do I authorize the users sending the request with their tokens to other services?
To elaborate the question:
Let'say I have three microservices.
1 ) ASP NET framework handling authentication and authorization, Which will authenticate a user and sends a token.
2 ) Orders service, Which will receive the requests with the token in their headers. (ASP NET core)
3 ) Accounting service, which will receive the requests with the token in their headers. (ASP NET core)
How do we authorize the users when they call service 2 or 3?
And Is this an ideal approach?
Instead of authenticating external requests at each microservice (you may want to do that for internal microservice communications), I would install a gateway (for example Ocelot which can handle the external "upstream" authentication for you using whatever system you're using, for example for Jwt bearer:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddJwtBearer("TestScheme", x => ...
}
Then in Ocelot you can decide which routes require this scheme as follows
"Routes": [{
"DownstreamHostAndPorts": [...],
"DownstreamPathTemplate": "/",
"UpstreamPathTemplate": "/",
"AuthenticationOptions": {
"AuthenticationProviderKey": "TestScheme", //<--here decide to use this scheme
"AllowedScopes": []
}
}]
If Authentication is successful you can use Ocelot's method of "claims to claims transformation" from your upstream to downstream this method - I personally wanted customise this and build a new Jwt token for internal authentication so used my own downstream handler, like this:
services
.AddHttpClient<IMyService, MyService>(client => ...)
.AddHttpMessageHandler<MyJwtDownstreamHandler>();
//then in the MyJwtDownstreamHandler
request.Headers.Authorization = new AuthenticationHeaderValue(
"bearer",
TokenGenerator.Generate( //<--generate your own Symmetric token using your own method
identity: myIdentity, //<--claims for downstream here
)
);
Based on comments Above
External Identity provider
You may need to use external identity provider e.g. identiyserver4 , azure ad or auth0 etc. Since the token may be generated is JWT token you will have to validate the token.
Validate Token
You need to validate the token in the .Net core Middle ware. Every token issued has a payload and your app middleware will verify every incoming token and reject if it's not able to validate. Your middle ware will fill the claims principle which can be used in your application to validate the authorization as well e.g. roles (if user has authorization to access particular api). You would put "authorize" attribute on top of controller and it will do the job.
You can validate the token manually or some identity provider gives automatic validation e.g. Azure Ad will validate the token and fill the claims principle without doing much effort by simply adding Azure ad nuget package.
There are heaps of example if you simply google. Tokens can be confusing so i would suggest you understand tokens e.g. id_token , access_token , refresh token . Authentication flows and claims. It would become easier if you understand the token types and flows. I am attaching very simple example just to give you idea.
Example
I am building a WebApi for external consumers. I want to lock it down using Azure AD B2C token authentication. .NET Framework 4.7.2 using Owin middleware.
The workflow (as I understand it) goes like this:
Successful path:
GET request on secure endpoint, contains a header with a valid auth token
API returns expected result
Invalid/missing token path:
GET request on secure endpoint, contains an invalid/missing token in the header(s)
API returns 401
This all looks correct from a security point of view, but my poor consumers won't know how to get a new token. Should I be returning something with the 401 to assist in them getting a new token? (i.e. the URL for the Azure AD B2C endpoint) - does this break conventional rules on returning objects with a 401? Am I expecting too much for my consumers to know how to interact with my chosen 3rd-party auth provider?
My question is more about design but would appreciate any technical examples.
How API Gateway and Micro services works.
Could anyone explain the basic flow of Micro service architecture with Gateway. I couldn't find the proper answer.
Say we have auth server and customer micro service running on separate instances and in front of all the services we have an API gateway.
My question is.
when user try to log in using username and password, the API gateway call auth server and return the access token to user.
Then user trying to access the specific url (/customers - customer micro service) that is running on separate instance.
what API Gateway do ?
validate the token with auth server and get the user id and pass the request to customer service with the user id ?
OR
validate the token and pass the request to customer microservice with the access token ? and customer microservice responsible is to the check the user id (Make an HTTP call to auth server) ?
I think that the most common approach is to use API gateway also as a security gateway, which means that API gateway is responsible for SSL termination and token validation. If token validation is successfully you can put user ID or user API key as a header and forward the request to microservice. Moreover you may also decide to perform not only authentication but also authorisation on the API gateway (usually with help of API management solutions).
Regarding your option #2 - I see no point in validating token 2 times. Best practise is to perform security validations on the edge, because in case of failed validation you use less resources (reject earlier)
To Answer your question , it is close to option #2 that you have mentioned . The API gateway will generally check the validity of the authentication token and then pass over the request to your micro-service . However you need to decide at design time if your micro-service will also do another level of verification of the token.
Please do note that the API gateway will not be enforcing Authorization , the authorization is something that your micro-service will have to enforce.