ASP.NET Core - having mTLS and OAuth2 at the same time - asp.net-core

I have ASP.NET Core RESTful APIs and protect them with JWT token issued from Azure Active Directory. Any client who wants to call the endpoints should first acquire a valid JWT token from the AAD and send that as a Bearer token. My API internally should call an external API (internal to the organisation) to query some information and return it to the user. The external API requires mTLS as its security protocol.
My questions
Can I still have my Bearer authentication scheme against my APIs and at the same time have mTLS enabled in my API so it can communicate with the third API?
From my understanding, in TLS which mTLS is an extension of it, the client should verify the server's certificate. Does that mean, with every incoming request I should check if it's presenting the certificate? If so, then what would happen to the Bearer authentication scheme then?
In my head, I was hoping that I can just append the certificate to the requests against the third-party API and that should be it but based on question number 2 I seem to be wrong about it.
I'm a bit lost here and appreciate any advice on this.

Related

How to protect an open API endpoint?

I have an API that doesn't have an authentication (intentionally). How can I secure it so only my application can make requests and API can identify those API requests coming from that server only?
Well, you need authentication 🤷
In order to verify who is calling your API you need to authenticate them. This doesn't mean that you have to authenticate users. Applications can also authenticate and present their identity to other applications. This is what you need here. You can achieve such app-to-app authentication in a few different ways:
Basic authentication. You can save an ID and a secret in your application and use them to send the Authentication header.
Use OAuth's client credentials flow. This is an OAuth flow that is made specifically for apps to identify themselves to other apps.
Use mutual TLS. You can tell your API what certificate will your application use and accept only connections with that certificate.
Identify with JWT Assertions. In this approach, your application signs a JWT with its ID and the API is able to verify the signature of the JWT.

JWT handling with WSO2-AM

we plan to introduce an API management solution and we're currently setting up a proof of concept with WSO2 AM. We want to use the WSO2 API gateway to check whether a certain consumer application is allowed to use an API and to throttle the request rate.
I work on the identity workflow and I wonder how a consuming application can pass a JWT token to the backend service with WSO2-AM in between.
First, this is our current scenario:
Without API gateway
The consuming application gets a JWT token for its carbon user from an identity provider. The JWT contains some claims about the user, e.g. the roles he/she belongs to.
The app calls the service an passes the JWT token in the Authorization HTTP header like: Authorization: Bearer
The service validates the issuer and signature of the JWT and retrieves the claims from it.
So, this is pretty straight forward. Now we put an API gateway in between the application and the service:
With API gateway
The consuming application gets a JWT token for its carbon user from an identity provider.
The consuming application uses OAuth2 to get an access token for the following API calls. We can use the client_credentials grant type and simply pass the the client id and client secret. I haven't yet tried it, but we could possibly use the JWT grant type (see https://docs.wso2.com/display/ISCONNECTORS/Configuring+JWT+Grant+Type) and use the JWT for passing user information to the API gateway.
The API gateway validates the JWT against the public key of the identity provider when using the JWT grant type.
An access token is returned to the app.
The app sends an API request to the gateway and passes the access token in the Authorization HTTP header.
The gateway validates the access token.
The gateway forwards the API request to the service.
And there is my problem: How can the JWT from 1/2. be passed to the service?
There is a documentation for "Passing Enduser Attributes to the Backend Using JWT" (see https://docs.wso2.com/display/AM210/Passing+Enduser+Attributes+to+the+Backend+Using+JWT), but this would introduce a new JWT, issued and signed by WSO2-AM, and I'm not sure, whether this JWT contains all information from the JWT used to create the access token (or even the original JWT).
Another way I could think of is using a custom HTTP header for passing the JWT through the gateway to the service. I cannot use the Authorization header (as we do without the API gateway), because WSO2-AM expects the access token in that header.
Since I'm not happy with either solutions, I want to ask the experts: How would you solve this?
Thanks,
Torsten
The only possibility I can think of is to send the JWT token in a custom Header for the backend service.

Using openid-connect for authentication spa and rest api

I have an API Server (Resource server) and multiple apps, Web GUI (SPA) and a Desktop client and maybe more coming.
I'd like to use openid-connect besides http basic authentication for my API Server.
It should be configurable which openid provider to use. My own, facebook, google...
I only want to do authentication, I do not need their API. I only need some profile data like email or firstname.
Let's say I have configured google as my IdP and I'm currently using my Web GUI (SPA). I need to login, no problem, according to https://developers.google.com/identity/protocols/OpenIDConnect I redirect the user to google, get my authorization code and the Web Gui (SPA) gets an id_token and access_token from google.
No problem so far, but now the SPA has to work with my API Server and the API Server needs to authenticate every request (since it is a stateless rest api) coming from the Client (WebGui SPA) and needs to know which user actually did this.
A
So the access_token from google is meant to be used to access google api's right? But I also could just pass this access_token with every request to my api server and the api server calls https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=xxx to verify the access_token and get the account name (mail). But this doesn't sound right, does it?
B
I also have and id_token which I can verify without calling google server everytime. So could I also just pass the id_token as bearer with every request to my api server and the api server can verify the id_token? But according to openid-connect spec the access_token is actually the one which just get passed to the api server and the id_token must stay on the client.
But then the id_token would be completely useless to me, the API server needs to know who the user is, the client (Web GUI) doesn't really care.
C
Or since it is my own API Server, does my API Server actually needs to implement the whole oauth2 system by itself, just not authentication but creating access_token and more. So I would have a /api/tokensign to which I can pass the id_token from google, the API verifies the id_token and creates an access_token for my WebGUI (SPA). And this new access_token can be passed as bearer to every api request. This actually sounds as the best solution according to specs, but do I really need to implement oauth2 by myself into my API? Sounds like a heavy addition since A and B could also be implemented.
My rest-api needs authentication with every request so is A, B, C the right approach? Please don't tell me this is opinion based, it is not.
What is the right way using oauth2/openid-connect for authentication?
You can use all three methods you have mentioned above, but indeed with some considerations. I will explain them with regards to available specifications.
Scenario - Two systems S1, S2
S1 - Identity provider
S2 - API endpoint
What you need - Trust and use 'Tokens' issued by S1 to access S2
Explanations for proposed solutioins A, B and C
A - Verify tokens issued by S1 for each call
This can be done using the RFC7662 - OAuth 2.0 Token Introspection endpoint. This validation is valid by the specification so yes you can use the token verification endpoint.
Advantage for this method is that, if a token is revoked, the effect is instantaneous. The very next API call will fail. But indeed there's the implication on performance. You need an extra verification service call.
Note that you do not need to get the account name from this verification response. It could be taken from ID token and could be used to verify for extra protection.
B - Trust tokens issued by S1 for each call
Now this approach is something extended from RFC6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage. You can indeed use ID toke to authenticate and authorise an end user. This link contains a good explanation on the ID token usage as a bearer token.
You can indeed verify the validity of token using MAC and even encryption. But be mindful to use short lived tokens and to always use TLS. And be mindful about refreshing tokens.! Because according to openID connect specification, ID token is not a mandatory item for a refresh token request.
C - A wrapper for federation
For this you can write your own solution or use an existing solutions (ex:- WSO2 identity server). This identity server will configured to choose the identity provider on your application (client like desktop app or web app). Identity server will do the necessary redirects and provide you the required tokens. But indeed you will need to use introspection endpoint to validate the token validity.
If you go one step ahead of this solution, you can try to implement a code exchange mechanism. You can exchange the token carry from external to tokens issued internally by one of your system (ex:- Google access token to your internal access token). The advantage of this approach is you have control over validation. Also since subsequent token validations are done internally, there should be a performance improvement.
Hope this explains some doubts you have.

Client authentication in microservices using JWT and OpenID Connect

I've some questions regarding authentication in a microservices architecture. I've right now a monolithic application and my goal is to split the application in small microservices.
My bigest problem is for authentication (for now). After reading a LOT a documentation, It seems that the best solution is to use OpenID Connect to authenticate an user to retrieve a JWT that can by passed with the request to the microservices.
Also, to avoid having multiple endpoints, you can deploy and API Gateway to have only one endpoint for the end user. Ok, so now I've two questions with this architecture.
The standard flow for authentication will be :
An user contact my identity server in OpenID Connect with the implicit flow and get the id_token (JWT) and also the access_token. The user can now contact my API with this access_token. The API Gateway will valide the access_token with the identity server and also retrieve the JWT to add it to the sub request to the microservice API.
1/ How the API Gateway can get the JWT from the access_token? From what I red from the documentation (http://openid.net/specs/openid-connect-core-1_0.html), It can contact the "/userinfo" endpoint but It will get just the JSON format not the JWT...
2/ I want to allow authenticated calls between my microservices. So each microservice needs to be able to generate a JWT to contact other microservices directly. My first thought was to contact the identity server. But with the OAuth2 Client Credentials flow, I don't retrieve a id_token or a JWT. Just a classic OAuth2 access token without JWT. My second thought was that the microservice can directly sign its own JWT with a certificate issued by the same PKI as the one used by the identity server. That mean that a JWT can be sign by several certificats but from the same private PKI. When a microservice receives a JWT, It needs to be able to identify witch certificat was used to sign the JWT. I don't find anything on the RFC regarding this problem. I can add my own private claim in the token to have the certificate but after several days of browsing the web without seeing this kind of solution, I'm wondering if I'm not on the wrong path... To sum up, how can i perfom "User to service" authentication AND alors "service to service" authentication in JWT?
Thank you very much!
I am implementing a similar solution. Not sure if it will address to your question completely, but, I hope it helps:
You can implement a new authentication micro-service to convert your oAuth2 access token to JWT token. This microservice will also sign this JWT token.
Your API gateway will route all client requests to authentication service, which will validate this token from IDM and will convert it to a signed JWT token.
API gateway will pass this JWT token to other microservices which will validate the signature from Authentication Service's public key. If the signature validates, roles can be extracted out of it for authorization.
Each microservice can have its own IDM credentials configured and when it wants to call any other microservice, it can generate an access token and call Authentication Service to get JWT which can be passed in call to other microservices.

How to combine user- and client-level authentication in an API gateway?

We're looking to implement web (external user) SSO and an API gateway to support web apps and mobile apps, and potentially 3rd party apps and even B2B scenarios.
My thought is to have the SSO gateway handle user-level access to websites and APIs, authenticating end users using OAuth or OpenID Connect.
Sitting behind this, for any API URLs, is the API gateway. This is intended to handle the client-/application-level authentication using something like a client ID and secret.
The idea would be that the user would log into a website or mobile app, and then if/when that app needed to call an API it would need to send its own credentials (client credentials flow) as well as a bearer token proving who the user is as well (resource owner password flow).
The client credentials are less about security and more about coarse-grained access to API functions, giving visibility of API usage, traffic shaping, SLAs etc., but the user identity is needed to enforce data-level authorisation downstream.
Most API gateways I've looked at appear to only support a single level of authentication, e.g. we're looking at Apigee at the moment that can use OAuth to authentication to handle either a user or an app, but it's not obvious how to do both at once.
Is there any way to get the SSO gateway's user bearer token to play nicely with the API gateway's client bearer token or credentials, preferably in a fairly standards-based way? Or do we just have to hack it so that one comes through in the auth header and the other in the payload? Or is there a way to have a combined approach (e.g. hybrid bearer token) that can serve both purposes at once?
I'm kind of surprised that with all the work going on in identity management (OAuth2, OpenID Connect, UMA, etc.) nobody is looking at a way of handling simultaneously the multiple levels of authentication - user, client, device, etc.
Unfortunately I don't have enough reputation points to comment on the previous post, so I'll add my two cents here. Full disclosure: I work for Apigee.
http://apigee.com/docs/api-services/content/oauthv2-policy#accesstokenelement explains how to give the access token to the Apigee OAuthV2 policy in a place other than the Authorization header. If you've stored the SSO bearer token as an attribute of the Apigee OAuth token then once the Apigee token is validated you'll automatically get the SSO bearer token as a flow variable and can use it as needed.
For example, if you send the token as a "token" query parameter on the request you can code the following in the OAuthV2 policy
request.queryparam.token
and the policy will pull it from that query parameter.