Yusbel Garcia
Yusbel Garcia

Reputation: 197

Azure AD B2C multitenants applications

I have been working in a solution to integrate a multi-tenant api backend system with multiple B2C directory, the idea is that each tenant own and manage their own directory, so our api backend system will need to be added to each tenant b2C directory.

I was thinking in extending the owin openID middleware as described here.

Active Directory B2C and OpenIdConnectAuthenticationMiddleware - Multitenant systems

Another alternative is to setup our own B2C directory to integrated our tenant's B2C directory.

Is this possible?

Upvotes: 1

Views: 404

Answers (1)

Thomas Pereira
Thomas Pereira

Reputation: 21

The client ID being referenced by the OWIN OpenIDConnect middleware in the context of Azure Active Directory is used to identify the application itself, regardless of tenancy.

For multi-tenant support, if you go into the "Configure" portion of the application, under the AD being used for application development, you should notice an option labeled "APPLICATION IS MULTI-TENANT" as shown in the screenshot.Multi-Tenant Option

Make sure Multi-Tenant support is enabled. There are other requirements for enabling multi-tenant support that will be obvious when attempting to enable that option.

This option will allow AADs of other tenants to consent to using your application. In action, once a AAD global admin for a tenant consents, this actually adds a reference to the application you have registered in your AAD to their AAD, allowing them to control access as desired without any change on your part.

Speaking to code, you must change the OWIN middleware to disable auto validation of the issuer, and implement your own mechanism for validating the issuer (such as storing all that information upon the initial registration of a tenant and checking all future tenant logins against the initially stored information). As follows:

            app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = ClientId,
                Authority = Authority,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // instead of using the default validation (validating against a single issuer value, as we do in line of business apps), 
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // we use this notification for injecting our custom logic
                    SecurityTokenValidated = (context) =>
                    {
                        // retriever caller data from the incoming principal
                        string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value;
                        string UPN = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
                        string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

                        if (
                            // the caller comes from an admin-consented, recorded issuer
                            (db.Tenants.FirstOrDefault(a => ((a.IssValue == issuer) && (a.AdminConsented))) == null)
                            // the caller is recorded in the db of users who went through the individual onboardoing
                            && (db.Users.FirstOrDefault(b =>((b.UPN == UPN) && (b.TenantID == tenantID))) == null)
                            )
                            // the caller was neither from a trusted issuer or a registered user - throw to block the authentication flow
                            throw new SecurityTokenValidationException();                            
                        return Task.FromResult(0);
                    }
                }
            });

Source: https://github.com/Azure-Samples/active-directory-dotnet-webapp-multitenant-openidconnect/blob/master/TodoListWebApp/App_Start/Startup.Auth.cs

The reason for disabling issuer validation is due to the common gateway being used in multi-tenant applications for AAD, so the issuer changes based on that tenant that's authenticating. There must be some store of appropriate issuers beforehand to compare with.

Upvotes: 2

Related Questions