Robert Muehsig
Robert Muehsig

Reputation: 5326

Multiple OpenIdConnectAuthentication-Middlewares for Multitenancy

We are trying to use the marvelous IdentityServer for our product. Your application should be able to work with different tenants and each tenant might have their own identityproviders.

The IdentityServer part "could" (it works, but I'm not sure if this is super clever) be solved like this:

 app.Map("/demotenant", (test) =>
        {
            test.UseIdentityServer(new IdentityServerOptions
            {
                SiteName = "Embedded IdentityServer",
                SigningCertificate = Certificate.Load(),
                Factory = factory,
                RequireSsl = false,
                AuthenticationOptions = new AuthenticationOptions
                {
                    EnableLocalLogin = false,
                    IdentityProviders = ConfigureIdentityProviders, 
                },
            });
        });

 app.Map("/demotenant2", (test) =>
        {
            test.UseIdentityServer(new IdentityServerOptions
            {
                SiteName = "Embedded IdentityServer",
                SigningCertificate = Certificate.Load(),
                Factory = factory,
                RequireSsl = false,
                AuthenticationOptions = new AuthenticationOptions
                {
                    EnableLocalLogin = false,
                    IdentityProviders = ConfigureIdentityProviders, 
                },
            });
        });

Now I tried to use this from my webapplication. When I'm working on /demotenant it should use the /demotenant-identity-server etc.

app.Map("/demotenant", (test) =>
{
    test.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        AuthenticationType = "cookies",
    });
    test.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions()
    {
        AuthenticationType = "oidc",
        SignInAsAuthenticationType = "cookies",
        Authority = "http://localhost:63958/demotenant",
        ClientId = "webapp",
        RedirectUri = "http://localhost:57354/",
        ResponseType = "id_token",
        Scope = "openid",
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            RedirectToIdentityProvider = async f =>
            {
                f.ProtocolMessage.AcrValues = "datasourceId:test";
            }, 
        },
    });
});

app.Map("/demotenant2", (test) =>
{
    test.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        AuthenticationType = "cookies",
    });

    test.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions()
    {
        AuthenticationType = "oidc",
        SignInAsAuthenticationType = "cookies",
        Authority = "http://localhost:63958/demotenant2",
        ClientId = "webapp",
        RedirectUri = "http://localhost:57354/",
        ResponseType = "id_token",
        Scope = "openid",
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            RedirectToIdentityProvider = async f =>
            {
                f.ProtocolMessage.AcrValues = "datasourceId:test";
            }
        },
    });
});

Unfortunately it doesn't work or at least I can't trigger the authentication flow.

My "simple" sample just use the [Authorize] attribute, which magically redirects me to my IdentityServer. So the question is:
- Is it possible to trigger one of the authroization based on a routing, if yes: How?

Upvotes: 0

Views: 923

Answers (1)

Saravanan
Saravanan

Reputation: 7854

Kindly note that, you should not have to use the app.Map to route to the Identity providers [IDP] based on the tenant. In the IdentityServer, you will have to figure out the exact IDP based on the tenant. Then you can just call the challenge on that particular IDP.

Steps

  1. Identify the tenant
  2. Look-up the IDP for the tenant
  3. Now, from the registered IDP's from the Owin Middlewares, you will have to invoke the challenge. 4.The end points / clientID & secrets are to be resolved from the identified tenant.
  4. This enables a fully dynamic pipeline without tenant specific routes as in a Multi-tenant production app, we do not want to make a fresh deployment update for each new tenant that we bring on-board.
  5. For Example, in case of a tenant opting for Social Identity providers, the loginmodel.Providers will contain all the login options like Facebook, Google, Twitter etc
  6. The user can choose and click on login.

Code sample to resolve the endpoint uris based on a tenant from an OWIN Middleware OnDemandEndpoints = async (clientid, EndpointUriTypes) => { var endpointResolver = ServiceLocator.Resolve<IClientEndpointResolver>(); return await endpointResolver.ResolveEndpointUri(EndpointUriTypes, clientid); },

There needs to be some context that can carry your tenant context across the middleware so that from the endpoint resolution to the clientId and ClientSecrets can be resolved dynamically.

Hope this is helpful for you

Upvotes: 1

Related Questions