Accept tokens from multiple identity providers in .NET Core
There’s at least 2 ways of interpreting the title of this post, it could mean:
- As an API, accept tokens coming from multiple applications that use different identity providers.
- As an application, allow a user to sign in using multiple 3rd party identity providers, and optionally act as an identity provider yourself by issuing your own tokens.
This post is mainly concerned with the first alternative.
Motivation
What’s the point of doing this then? Well in our case it’s that the main application the API was built to serve (an administration application) authenticates against the organizations AAD (Azure AD). The application that will now be granted access to the API is however a customer facing application which authenticates the user against Auth0, and it’s not currently in scope to change the admin application to authenticate against Auth0 for business reasons.
Illustration of what we’re trying to accomplish
The code
All the code that we need to change (to get this to work, if you have any custom authorization then you might need to change that as well) is in the public void ConfigureServices(IServiceCollection services)
method of our Startup.cs
file.
Before we start adding the new idp
(identity provider, Auth0 in this case) our ConfigureServices
look something like this:
With this code we have an API that will accept tokens from AAD with the aud
claim set to the application id for the API when registered in AAD (it’s up to the calling application to specify that the requested token is for this API).
Now we will need to make some small changes to be able to accept either a AAD OR Auth0 token.
As you can see we’ve added another call to AddJwtBearer
which as identical to the first call, except for the values of the properties. You might also see that we’ve used the named AddJwtBearer
overload which is necessary to be able to use both of them, otherwise the last call would “win” and only that registration would actually be checked against. This also allows us to add different idps
to different policies, for instance to only allow one idp
to a admin endpoint but everyone to all the normal endpoints, but in our case we add both idps
to our “Api” policy. It should be possible to add them to either the new AuthorizationPolicyBuilder
constructor, or to the AddAuthenticationSchemes
call, but I’ve only gotten it to work by adding it to both.
The last thing we do is to set our “default” idp
name in the call to AddAuthentication
.
Things you might need
If you have the need to somewhat normalize the user information from multiple idps
, for instance if you use the User.Identity.Name
in a controller, then you may use the OnTokenValidated
event to controll how the idp
token claims flow into your ClaimsIdentity
.
Resources used when finding this solution
- https://github.com/aspnet/Security/issues/1708#issuecomment-376567491
- https://github.com/aspnet/Security/issues/1664
- https://stackoverflow.com/questions/49694383/use-multiple-jwt-bearer-authentication
- https://joonasw.net/view/adding-custom-claims-aspnet-core-2
- https://github.com/aspnet/Security/issues/1310