OpenIDConnect .Net框架中的多租户

3
我正在尝试实现多租户身份验证(我正在学习),到目前为止,我已经成功地在单个租户中实现了应用程序的身份验证。
我用于单个租户的代码是:
 public void ConfigureAuth(IAppBuilder app)
        {

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseOpenIdConnectAuthentication(
                 new OpenIdConnectAuthenticationOptions
                 {
                     ClientId = ConfigurationManager.AppSettings["AuthclientId"],
                     Authority = "https://login.microsoftonline.com/abc.onmicrosoft.com/",



                 });
        }

这里,我首先在ABC AAD中注册我的应用程序并获取客户端ID,然后将其放入我的配置中。一切正常。
但现在我必须使用多租户类型来实现这一点。即使它是多租户,我也只允许两个租户用户。假设是abc.onmicrosoft.com和contoso.onmicrosoft.com。
到目前为止,我已经在ABC租户和Contoso租户中注册了我的应用程序,然后获取了两个客户端ID。但我的问题是无法在UseOpenIdConnectAuthentication(请参见下面更新的代码)中提供2个客户端ID。
public void ConfigureAuth(IAppBuilder app)
        {

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseOpenIdConnectAuthentication(
                 new OpenIdConnectAuthenticationOptions
                 {

                     ClientId = ??,
                     Authority = "https://login.microsoftonline.com/common/",
                     TokenValidationParameters = new TokenValidationParameters
                     {
                         ValidateIssuer = false
                     },

                 });
        }

附言:这对我来说是新的。我可能错了,请纠正我以便把事情走在正确的轨道上。
更新1:
app.UseOpenIdConnectAuthentication(
             new OpenIdConnectAuthenticationOptions
             {

                 //ClientId = authClientID1,//App ID registered with 1st Tenant
                 Authority = "https://login.microsoftonline.com/common/",
                 RedirectUri= "https://localhost:44376/",
                 TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidAudiences = new List<string>{ authClientID1, authClientID2 },
                     ValidateIssuer =true,
                     ValidIssuers= new[] { "https://sts.windows.net/<tenantID1>/", "https://sts.windows.net/<tenantID2>/" }
                 },

             });

在注释掉ClientID后,我收到了以下错误:
AADSTS900144:请求正文必须包含以下参数:'client_id'
我不确定如何提供我的两个ClientID和租户ID,以便仅从我的两个租户对用户进行身份验证!
2个回答

2
为了提供一个多租户应用程序,您只需在 AAD 中创建一个应用程序。因此,您也只有一个 client_id。确保您的应用程序启用了“多租户”功能。
您可以在这里找到更多信息:https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-convert-app-to-be-multi-tenant 还有一个完整的示例可用: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);
                    }
                }
            });

    }

1

你的客户端ID应该是你的应用程序客户端ID。不要在另一个租户中创建另一个应用程序。将权限设置为common就足够了。如果您想允许任何租户,则可以禁用发行者验证。

然后,当来自另一个租户的用户登录到您的应用程序时,他们将被要求同意所需的权限。一旦他们同意,代表您的应用程序的服务主体会在其租户中自动创建。它具有相同的客户端ID。


谢谢你的回答。我想我明白了你的意思。但是根据我的需求,我只想允许来自两个特定租户的用户,而不是其他人。在这种情况下,我们该如何实现呢? - Jayendran
啊,你遇到了我所说的N租户情况。在这种情况下,不要禁用发行者验证。保留公共授权,没有选择。然后,在TokenValidationParameters中指定ValidIssuers。发行者字符串始终为“https://sts.windows.net/{tenantid}/”,因此添加两个并将{tenantId}替换为两个AAD的目录ID。 - juunas
@junnas 是的,现在它可以工作了。但是正如我之前所说,当我尝试使用第二个目录中的用户登录时,它会给我一个错误,例如"AADSTS700016: 在目录 'xxx-xxxx-xx.(TenantID)' 中找不到标识符为'xx-xxxx-xxxxx'(clientId)的应用程序",这是由于clientId已经注册到租户1,所以它会出现这个错误。 - Jayendran
让我们在聊天中继续这个讨论 - Jayendran
你能帮我解决这个问题吗?我无法解决这些问题。 - Jayendran
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接