Authentication with multiple services: Only one REST-call or multiple calls? - api

I have a question about using JWT in a webapp: An auth-service provides a JWT which gives me the information whether the user is known or not. Then another service will be called to check the user roles based on the JWT. It appends an API-key, the user roles and will call the real API.
Now my question: What ist the best auth flow?
Should the webapp do only one call: Calling the JWT-service which proxies the request to the auth service and this service proxies it to the real backend and all the way back?
Or should it look like this: Webapp calls JWT-service. The JWT-service returns the JWT to the webapp and then the webapp will call the auth-service in a second request.
Unfortunately the JWT-service cannot check the userroles :(
Are there any advantages/disadvantages or BestPatterns?
I hope that is not too confusing:D
Best
Lukas

I think you should consider using an API Gateway between your frontend and the underlying microservices. That Gateway will take care of forwarding all the calls.
For example, it will call the auth-provider which will build the JWT.
This token, in turn, should contain all the relevant roles for the logged-in user, exposed as claims.
JWT validation doesn't necessarily require a service call.
I wrote a blog post a while ago explaining the flow more in details: https://www.davideguida.com/handling-authentication-and-authorization-in-microservices-part-2/

Related

How to use authorization in Gateway for a .NET microservice based app using Ocelot

We have a .NET microservice based app where the Gateway is built using Ocelot. Until now we didn't do any authentication in the Gateway, the frontend calls an Authentication Provider service which responds with an JWT token, the token gets added to request headers and then, the new requests go through gateway and each particular microservice is concerned with authentication and authorization.
We also have API Key based authentication in place, but it's not used until now.
I added a new microservice with authentication done by API Key and I want to handle authorization in the Gateway. That means the gateway should check the claims based on JWT token and if claims matches forward the request to the microservice using an API key header.
How can I do it with Ocelot, instead of writing controllers and actions for each corresponding microservice controllers and actions? I thought about implementing Delegating Handlers to take care of it, but maybe there is a better way?
A clean way to do this, is to have the access token between the client and the API gateway and to then use the token exchange flow between the gateway and the underlying APIs so as to keep a potential attack surface on the initial access token small and avoid exposing internal mechanics (e.g. multiple audiences of underlying APIs in your initial access token, multiple api scopes).
There are many sources of information about this online. Here's one to get you started.

Integration of frontend and resource server using okta authentication and client credentials API authentication

We have an application that has frontend UI(Which is a web application) which communicates with a resource server. Our frontend will be using some APIs from a resource server to get data.
I am planning to add frontend to Okta and provide access to okta registered users.
In the resource server, we have some APIs that we want to expose to our customers to integrate in their system(Programmatically). To use our APIs, we have to provide client credentials(client ID/secret) to them. Using clientId/Secret, they will get access_token and will use that in a subsequent request. We can display this clientId/Secret via frontend UI once the user logs in to it via Okta.
How should I authenticate requests to the resource server from the frontend? And how do I authenticate requests to resource server via customer using clientId/Secret? Should I use one or two different tokens for this purpose?
Does Okta provides per-user client Id/secret that user(customer) can use to get access_token and send it to access resource server and resource server validate token against Okta.
I just did something very similar. You can read about my experience here: How to pass/verify Open ID token between .net core web app and web api?
I don't know what application framework you are using (.net, node, etc), but if you're using .NET the steps are to (a) install the middleware in your web app, (b) install the middleware in your api app, and (c) make sure calls from your web app to the api app pass the id_token.
If you, in addition to that, need to secure it for external users - it should work the same way. The only difference is they will manually call the /authorize endpoint to get their token - but the middleware should take care of the token verification for you in both cases.
Note I did experience one odd thing which is that I needed to pass the id_token and not the access_token. It is also worth mentioning that the claims were interpreted differently in the app and the api (in that the name of the claims for say, userid, were different between them - the data was still the same).
You will have to use 2 different access tokens. There are 2 different flows going on here:
Web UI to API
Business partner system to API
Technically this means:
Authorization Code Flow (PKCE)
Client Credentials Flow
And in terms of tokens it means:
In the first case there is an end user represented in access tokens (the 'sub' claim)
In the second case there is only a Client Id claim in access tokens
I can advise on token validation techniques if needed - let me know.
To me though this feels like an architectural question - in particular around applying authorization after identifying the caller and versioning / upgrades.
Based on my experience I tend to prefer the following architecture these days, based on 2 levels of APIs: eg with these ones exposed to the internet:
User Experience API serves the UI
Partner API deals with B2B
And both entry point APIs call the same core services which are internal. Might be worth discussing with your stakeholders ..

How to send user details to backend API if client user was authenticated at the API Management service front end?

I'm interested in using Azure APIMS to authenticate requests from a client app using Azure AD. However, I am interested in having the backend API know details about the user who was authenticated at the gateway such that I can perform logic based on that user.
Backend API would be ASP.NET Core 3.x web api.
What approaches are available to me?
One thing I can think of off the top of my head is to simply forward the Authentication header along to the backend API, and do some type of lookup there. But I am wondering if there is any way for me to aggregate the user details at the frontend api gateway layer, and pass that information along in a header?
How are backend applications obtaining details about the authenticated user when requests are authenticated at the frontend gateway layer?
I realize that if I was to add authentication at the backend API layer (which would duplicate the authentication/authorization) I may be able to technically accomplish it this way. However, this would violate the SRP principle and perhaps add some necessary overhead to the backend.
Azure AD authentication at APIM would mostly imply validating JWT token passed along with request. You can callout to other endpoints if you want to with send-request policy to obtain more information (for example, do group expansion), but that would have to be explicitly configured through policies.
After token is validated it's available to you in object model form so you can inspect its properties and use any part of the token in policy expressions, say to send parts of it as headers to your backend API.

OAuth for Microservices with API Gateway - architecture

In a microservice architecture, an API gateway lays in front of the API. The purpose of this is e.g. changing some request / response parameters, for single entry point or checking authentication etc. Now I would like to protect my API using OAuth2 flows to obtain an access token. The problem is to decide who is the actual OAuth client, I will demonstrate it by using a SPA example:
a) Is it the SPA that started the oauthorize request (to the api gateway) by using the implicit grant. Then, the Api gateway would simply route the request through to the OAuth authorization server, acting as a single entry point, with the /authorize stuff from the implicit flow
b) Is it the API Gateway itself, meaning the SPA sends the username and password of the enduser to the api gateway (of course, here the SPA needs to be trusted with the end users credentials), which then acts on its own as an oauth client using the resource owner password grant
c) dismiss the api gateway at all and create the oauth authorization server "parallel" to the api gateway, meaning you would loose the single entry point etc.
The following picture demonstrate a very abstract architecture, and the question is about the numer "[2]", if this request is initiated by the SPA and passed through by the api gateway, or if the api gateway is intercepting the request and acting on its own as an oauth client?
OAuth with API Gateway
My guess is to always use the best fitting grant type for a specific client, regardless of an API gateway being in between or not. This would mean, that when it comes to OAuth, the API Gateway would simply pass the client authorization request through, whatever grant type it used. Therefore, [2] in the picture would come from the client, and not from the API Gateway acting as the OAuth client. Is this correct? As mentioned, this really gets tricky when it comes to first party apps as you probably could use the password credentials grant, which has huge drawbacks,e.g. no refreshing possible for SPAs.
Please bear in mind that this is a purely opinion based answer, because your question is pretty vague.
I don't like the idea about using the API Gateway as the point which authenticates requests. I think that this defeats the Single Responsibility Principle. The gateways purpose usually is to expose your backend to external clients, perhaps change the contract for some specific clients, etc. But it shouldn't also authenticate calls. Besides it would have to do so based on the data passed to it, which you would have to gather somewhere else anyway.
Another thing which is I think undesirable, is that you're considering using the resource owner password grant for your SPA. This is not the correct use case for this grant flow. You could look into this article, which explains it much better than I could: https://www.scottbrady91.com/OAuth/Why-the-Resource-Owner-Password-Credentials-Grant-Type-is-not-Authentication-nor-Suitable-for-Modern-Applications
I would suggest you use the Implicit grant type and use the api gateway to only route calls to the backend, don't authenticate the calls on that layer.
If you're using a spring cloud api gateway (essentially a zuul proxy), you will have to add proper configuration so that it forwards all security headers and redirects. This example works for me:
server:
use-forward-headers: true
zuul:
addHostHeader: true
routes:
<your oauth server route>:
url: <your oauth server url>
path: <if youve got any prefix>
sensitiveHeaders:
stripPrefix: false
It doesn't matter, what Krzysztof Chris Mejka in previous answer like or dislike. Take a look at BCP - https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps#section-6
Latest recommendation from oauth working group at IETF is to use a kind of Api gateway/reverse proxy, another words - you need to keep tokens out of js entirely.

Authentication and authorisation in microservice architecture

I have multiple services:
User
Post
Comment
Authentication
GraphQL endpoint
And let's say they are connected together like this:
All services are communicating through gRPC on a closed nettwork and the Authorization is done using jwt tokens
Approach 1:
The graphql service is responsible for user authentication and making sure that the user is authorized to run the specified procedure. There is no user authentication between the services, but there is TLS authentication. There are no authorization checks done by the services.
Approach 2:
Each individual service makes sure that the user is authorized to run a specific procedure. An example could be voting on a post where you would need to be signed in and have over 15 in reputation. Here it would be the Post service's responsibility to check whether the user is signed in or not (authenticated) and whether it's authorized to vote. This will result in large overhead since every procedure call needs to check user authentication and authorisation through the Auth service.
Is there a better approach that still preserves the security of approach 2, but creates a small overhead like approach 1?
-----Update-----
Approach 3:
Same as approach 2, but user authentication is only done in the GraphQL service using the Auth service. The authorization is done by checking metadata passed around. And there is TLS authentication between the services.
Let's consider a request that travels from the authenticated user to service A and on to service B. The JWT should be passed on each of these calls.
Both services would first authenticate the user which is simply done by validating the JWT. Then each service would extract all information necessary to authorize the user from the user, for example the sub claim. It would use this information to decide if the user is authorized with respect to the operation that the service shall perform on behalf of the user. Only after successful authorization would the service actually do anything.
This would not be overhead but necessary to allow service B to both authenticate and authorize the user. Not passing the JWT from sercice A to service B would make it impossible for service B to know anything about the user.