我有一个ASP.NET核心web应用程序,它在使用Microsoft.Identity.Web的多租户配置中与Azure进行身份验证。我们使用租户/公司标识符作为应用程序URL的子域。(companyA.myapp.com,companyB.myapp.com)。有些用户可以访问应用程序的多个租户,因此我们不能将Azure AD租户直接映射到应用程序中的单个租户/公司。
对于Microsoft.Identity.Web,状态参数是如何设置或操作的,如本文所述?我想遵循这里提供的指导,但不知道从哪里开始。https://learn.microsoft.com/en-us/azure/active-directory/develop/reply-url#use-a-state-parameter
如果您有几个子域,并且您的场景要求在成功的身份验证之后,您将用户重定向到他们开始时所在的页面,使用状态参数可能会有帮助。在这一办法中:
发布于 2021-10-12 16:29:33
下面是我如何最终解决MS无限重定向与租户每个子域方案的问题。)试图想出一个更好的名字来解决这个问题。)
提供一个SigninRedirect控制器操作,该操作接受我们必须验证的returnUrl参数,以避免成为开放重定向。
将returnUrl设置为companyA.example.com/foo&bar=1的示例URL
https://signin.example.com/signin-redirect?returnUrl=companyA.example.com%2Ffoo%26bar%3D1[Route("")]
public class SigninController : Controller
{
private readonly IMediator _mediator;
private readonly IConfiguration _configuration;
public SigninController(IMediator mediator, IConfiguration configuration)
{
_mediator = mediator;
_configuration = configuration;
}
[Authorize]
[HttpGet("/signin-redirect")]
public IActionResult SigninRedirect(string returnUrl)
{
string redirect;
if (!string.IsNullOrEmpty(returnUrl) && IsValidSubdomainUrl(returnUrl))
{
redirect = returnUrl;
}
else
{
var appHost = _configuration.GetValue<string>("General:ApplicationHost");
var home = new UriBuilder("https", appHost).Uri;
return Redirect(home.AbsoluteUri);
}
return Redirect(redirect);
}
/// <summary>
/// Avoid Open Redirect Vulnerability
/// https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html
/// </summary>
/// <param name="returnUrl"></param>
/// <returns></returns>
private bool IsValidSubdomainUrl(string returnUrl)
{
var appHost = _configuration.GetValue<string>("General:ApplicationHost");
var isValid = Uri.IsWellFormedUriString(returnUrl, UriKind.Absolute) &&
Uri.TryCreate(returnUrl, UriKind.Absolute, out var uri) &&
uri?.Host.EndsWith(appHost) == true;
return isValid;
}
}在ConfigureServices(IServiceCollection服务)中,将cookies设置为跨所有子域共享,并配置一个OnRedirectToIdentityProvider事件,以便在用户尚未通过身份验证时重定向到您的签名URL:
var cookieDomain = _configuration.GetValue<string>("General:CookieDomain");
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromDays(3);
options.Cookie.Domain = cookieDomain;
options.Cookie.Path = "/";
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
_configuration.Bind("AzureAd", options);
options.Events ??= new OpenIdConnectEvents();
options.Events.OnRedirectToIdentityProvider += context => {
var originalRequestUri = context.HttpContext.Request.GetUri();
var signInHost = _configuration.GetValue<string>("General:SignInHost");
var signInPath = _configuration.GetValue<string>("General:SignInUrl");
if (!originalRequestUri.Host.Equals(signInHost, StringComparison.InvariantCultureIgnoreCase))
{
var signInUrl = QueryHelpers.AddQueryString(signInPath, "returnUrl", originalRequestUri.AbsoluteUri);
// When on a subdomain and not authorized, then redirect to
// our signin URL.
context.Response.Redirect(signInUrl);
// Let Microsoft.Identity.Web know that we already handled
// this redirect
context.HandleResponse();
}
return Task.CompletedTask;
};
},
cookieOptions =>
{
cookieOptions.Cookie.Domain = cookieDomain;
cookieOptions.Cookie.Path = "/";
cookieOptions.Cookie.SameSite = SameSiteMode.Lax;
})
.EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" })
.AddDistributedTokenCaches();
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Domain = cookieDomain;
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.Path = "/";
options.Cookie.SameSite = SameSiteMode.Lax;
});定义的配置:
"General:CookieDomain": ".example.com",
"General:ApplicationHost": "example.com",
"General:SignInHost": "signin.example.com",
"General:SignInUrl": "https://signin.example.com/signin-redirect"此外,您还需要使用来自AzureAd的常规用于Azure AD的Microsoft Docs配置部分。
"AzureAd:Instance": "https://login.microsoftonline.com/",
"AzureAd:Domain": "...",
"AzureAd:TenantId": "common",
"AzureAd:ClientId": "...",
"AzureAd:ClientSecret": "...",
"AzureAd:CallbackPath": "/signin-oidc",
"AzureAd:SignedOutCallbackPath": "/signout-callback-oidc",

https://stackoverflow.com/questions/69225390
复制相似问题