How to Configure multi tenant by using Open Id connect in ASP .NET Framework 4.8

Rehan Akbar 0 Reputation points
2023-08-31T07:51:23.31+00:00

How to Configure multi tenant by using Open Id connect in ASP .NET Framework

I tried with this approach but when the second request pass to the middleware it didn't choose the 2nd tenant.

   app.Use(async (context, next) =>
                {
                    tenantIdentifier = GetTenantIdentifierFromRequest(context.Request);

                    // Update authentication configuration for the specific tenant
                    ConfigureOpenIdConnectAuthentication(app, tenantIdentifier);
                    // Set the current tenant context
                    TenantContext.SetCurrentTenant(tenantIdentifier);

                    await next();
                });
Account Controller
 public ActionResult LogIN()
        {
            if (Request.IsAuthenticated)
            {
                
            }
            else
            {
                
                HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/Home/Index" },
                  OpenIdConnectAuthenticationDefaults.AuthenticationType);
            }
            return View();
        }
HomeController is [Authorize]
  public ActionResult Index()
        {
        
            return View();
        }
  app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                
                ClientId = GetClientIdForTenant(tenantIdentifier),
                Authority = GetAuthorityForTenant(tenantIdentifier),
                PostLogoutRedirectUri = postLogoutRedirectUri,
                RedirectUri = RedirectUri,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    AuthenticationFailed = async n =>
                    {
                        if (string.Equals(n.ProtocolMessage.Error, "access_denied", StringComparison.Ordinal))
                        {
                            n.HandleResponse();

                            await Task.Yield();

                            n.Response.Redirect("/");
                        }
                           else
                        {
                            n.HandleResponse();
                            n.OwinContext.Authentication.Challenge();
                        }
                    }
                                  

                }
            });


Microsoft Authenticator
Microsoft Authenticator
A Microsoft app for iOS and Android devices that enables authentication with two-factor verification, phone sign-in, and code generation.
5,708 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,330 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Lan Huang-MSFT 26,761 Reputation points Microsoft Vendor
    2023-09-01T02:31:01.5166667+00:00

    Hi @Rehan Akbar,

    To deliver a multi tenant application, you only create one application in AAD.

    Therefore you also only have one client_id. Make sure your app has "Multi-Tenanted" enabled.

    You find much information here: https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-convert-app-to-be-multi-tenant

    There is also a full sample available: https://github.com/Azure-Samples/active-directory-dotnet-webapp-multitenant-openidconnect

     public void ConfigureAuth(IAppBuilder app)
        {         
            string ClientId = ConfigurationManager.AppSettings["ida:ClientID"];
            //fixed address for multitenant apps in the public cloud
            string Authority = "https://login.microsoftonline.com/common/";
    
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    
            app.UseCookieAuthentication(new CookieAuthenticationOptions { });
    
            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()
                    {
                        RedirectToIdentityProvider = (context) =>
                        {
                            // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                            // this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
                            // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                            string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;                         
                            context.ProtocolMessage.RedirectUri = appBaseUrl;
                            context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
                            return Task.FromResult(0);
                        },
                        // 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);
                        },
                        AuthenticationFailed = (context) =>
                        {
                            context.OwinContext.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
                            context.HandleResponse(); // Suppress the exception
                            return Task.FromResult(0);
                        }
                    }
                });
    
        }
    

    source

    Best regards,
    Lan Huang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments