OpenIDConnect .Net Framework 中的多租户
Multi-tenant in OpenIDConnect .Net Framework
我正在尝试实施多租户身份验证(我正在学习),到目前为止,我已经成功地在单租户中实施了我的应用程序的身份验证。
我用于单租户的代码是
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,然后将其放入我的配置中。一切正常。
但现在我必须使用多租户类型来实现它。即使它是多租户,我也只允许 2 个租户用户。假设 abc.onmicrosoft.com
和 contoso.onmicrosoft.com
到目前为止,我已经完成了在 ABC
租户和 Contoso
租户中注册我的应用程序,然后获得 2 个客户端 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
},
});
}
P.S 这对我来说是新的。我可能是错的,请指正我以使事情走上正确的道路
Update 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>/" }
},
});
After commenting the ClientID I'm receiving the error like
AADSTS900144: The request body must contain the following parameter:
'client_id'
我不确定如何提供我的两个 ClientID 和租户 ID 以便仅对来自我的两个租户的用户进行身份验证!
您的客户端 ID 应该是您的应用程序客户端 ID。您不会在其他租户中创建另一个应用程序。设置权限为common即可。如果您想允许任何租户,可以禁用颁发者验证。
然后,当其他租户的某人登录到您的应用时,系统会要求他们同意您所需的权限。一旦他们这样做,代表您的应用程序的服务主体就会自动在他们的租户中创建。它具有相同的客户端 ID。
要交付多租户应用程序,您只需在 AAD 中创建一个应用程序。因此你也只有一个client_id。确保您的应用已启用 "Multi-Tenanted"。
您可以在这里找到很多信息:https://docs.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);
}
}
});
}
我正在尝试实施多租户身份验证(我正在学习),到目前为止,我已经成功地在单租户中实施了我的应用程序的身份验证。
我用于单租户的代码是
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,然后将其放入我的配置中。一切正常。
但现在我必须使用多租户类型来实现它。即使它是多租户,我也只允许 2 个租户用户。假设 abc.onmicrosoft.com
和 contoso.onmicrosoft.com
到目前为止,我已经完成了在 ABC
租户和 Contoso
租户中注册我的应用程序,然后获得 2 个客户端 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
},
});
}
P.S 这对我来说是新的。我可能是错的,请指正我以使事情走上正确的道路
Update 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>/" }
},
});
After commenting the ClientID I'm receiving the error like AADSTS900144: The request body must contain the following parameter: 'client_id'
我不确定如何提供我的两个 ClientID 和租户 ID 以便仅对来自我的两个租户的用户进行身份验证!
您的客户端 ID 应该是您的应用程序客户端 ID。您不会在其他租户中创建另一个应用程序。设置权限为common即可。如果您想允许任何租户,可以禁用颁发者验证。
然后,当其他租户的某人登录到您的应用时,系统会要求他们同意您所需的权限。一旦他们这样做,代表您的应用程序的服务主体就会自动在他们的租户中创建。它具有相同的客户端 ID。
要交付多租户应用程序,您只需在 AAD 中创建一个应用程序。因此你也只有一个client_id。确保您的应用已启用 "Multi-Tenanted"。
您可以在这里找到很多信息:https://docs.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);
}
}
});
}