10

When using .AddOpenIdConnect() within ConfigureServices, is it possible to change the ClientId and ClientSecret based on the host from the request?

I know the Startup itself doesn't have access to the HttpContext, but I was wondering if using a middleware would solve this where it would have access to the context.

I've tried following the below link, however my values are always null after it runs through the CustomAuthHandler ASP.NET Core 2.0 authentication middleware

garfbradaz
  • 3,052
  • 7
  • 35
  • 64
niko619
  • 374
  • 7
  • 17
  • The ClientId is used to identify your app. You don't need to change it, nor the password if you configure your oids server for multiple hosts. – Ruard van Elburg Jan 15 '18 at 14:56
  • I'm curious what is the motivation for this? – juunas Jan 15 '18 at 19:37
  • The purpose is for multi tenancy. Each tenant will have it's own auth provider account. Therefore, the id and secret will be different between tenants – niko619 Jan 16 '18 at 05:33
  • Client login is typically for server to server communication. If you are hosting the app, how are you going to allow the tenant to use it? Does the tenant have to login for that? I think there are two scenarios: the tenant has its own app where clientid/secret must be used (configure multiple clients in the oidc server and set the right scope to access the resource), or the tenant is a user and logs in. In that case the user is identified and along with your apps credentials (which do not change and are kept secret!) the resource can be accessed. – Ruard van Elburg Jan 16 '18 at 10:20
  • For the user you use grant_type=password, while for the client you use grant_type=client_credentials. These are different flows. – Ruard van Elburg Jan 16 '18 at 10:26
  • @RuardvanElburg The project is using Auth0 as the login provider. It's using Cookies but. if a cookie doesn't exist, the user gets redirected to the Auth0 hosted login page. It only knows the correct Auth0 page based on id, secret and audience being set. Hence the need for it to change depending on the sub domain the user id navigating to. – niko619 Jan 16 '18 at 14:56
  • Correct me if I'm wrong, but isn't Identity Server the tool for this? [Identity Server 4](https://identityserver.io/) it is design for multi tenancy. Another solution that comes to my mind is using databases or json files to get the data from there, if it depends on the host they are connecting from you can use an API that recognizes the host and then checks the db or json file to assign the client credentials – Fede Antuña Jan 19 '18 at 03:43
  • @FedeAntuña I do have a json config file. The issue is 'how' to update the clientId and clientSecret at runtime – niko619 Jan 19 '18 at 10:51

1 Answers1

5

I believe you can achieve your goal assigning function to RedirectToIdentityProvider property.

Invoked before redirecting to the identity provider to authenticate. This can be used to set ProtocolMessage.State that will be persisted through the authentication process. The ProtocolMessage can also be used to add or customize parameters sent to the identity provider.

public void ConfigureServices(IServiceCollection services)
{
    services
    .AddAuthentication()
    .AddOpenIdConnect(options =>
        {
            options.Events.OnRedirectToIdentityProvider = context =>
             {
                  // Retrieve identity from current HttpContext
                  var identity = context.HttpContext.User.Identity;

                  // Lookup for your client_id and client_secret
                  var clientId = "find your client id";
                  var clientSecret = "find your client secret";

                  // Assign client_id and client_secret
                  context.ProtocolMessage.ClientId = clientId;
                  context.ProtocolMessage.ClientSecret = clientSecret;

                  return Task.FromResult(0);
              };
         });
}

Related links

OpenIdConnectEvents.OnRedirectToIdentityProvider Property

dropoutcoder
  • 2,049
  • 1
  • 8
  • 23
  • 1
    While this points me in the right direction, it's not the full answer. You also need to update the 'context.ProtocolMessage.ClientId' and the 'context.Options.TokenValidationParameters.ValidAudience'. Otherwise you run into conflicts of info in the current request – niko619 Jan 24 '18 at 08:56
  • 1
    Okay, I will update the answer to make it completely correct. Thanks for update. – dropoutcoder Jan 24 '18 at 10:31
  • @niko619 this implementation leaks a client secret. – Calvin Dallimore Mar 10 '20 at 19:49
  • @dropoutcoder I am getting this error message when changing the clientId and clientSecret dynamically `Message contains error: 'invalid_grant', error_description: 'The specified authorization code cannot be used by this client application.', error_uri: 'error_uri is null'.` – Mahendran Oct 29 '20 at 16:48
  • @Mahendran: It is most likely a problem with settings on the auth server side. – dropoutcoder Oct 30 '20 at 13:47