C# 在“上提供授权保护SPA”/&引用;在使用azure auth之前使用BFF和自定义登录屏幕
我意识到这个问题听起来很长很复杂!我会尽力解释的。 我有一个ASP.NET Core 5应用程序,它是我的Angular应用程序的BFF(前端后端)。您必须使用Azure AD登录才能访问SPA。其结果保存在cookie中,因此我们有两个身份验证方案(Azure AD和cookie)。图像等资源无需经过身份验证即可访问 问题是我有一个HomeController,它有一个C# 在“上提供授权保护SPA”/&引用;在使用azure auth之前使用BFF和自定义登录屏幕,c#,angular,asp.net-core,authentication,azure-active-directory,C#,Angular,Asp.net Core,Authentication,Azure Active Directory,我意识到这个问题听起来很长很复杂!我会尽力解释的。 我有一个ASP.NET Core 5应用程序,它是我的Angular应用程序的BFF(前端后端)。您必须使用Azure AD登录才能访问SPA。其结果保存在cookie中,因此我们有两个身份验证方案(Azure AD和cookie)。图像等资源无需经过身份验证即可访问 问题是我有一个HomeController,它有一个Index()操作,该操作有一个[AuthorizeForScopes]和[authorized]属性,用于检查用户是否登录并
Index()
操作,该操作有一个[AuthorizeForScopes]
和[authorized]
属性,用于检查用户是否登录并授权了作用域。如果没有,则AuthorizeForScopes
将把它们带到Microsoft登录页面。如果他们已登录,该方法将重定向到SPA运行的/home
此设置存在一些问题:
- 我希望SPA在
/
- 无法执行此操作,因为
方法在那里运行HomeController.Index()
- 使用类似于
的方法不是一个很好的解决方案;在开发过程中,由于Web包代理等原因,路径不同。。。在生产过程中,由于某些原因,SPA没有正确加载returnphysicalfile(..)
- 无法执行此操作,因为
- 如果用户没有登录,我想显示一个服务器端呈现的登录屏幕,它充当应用程序的“介绍页面”。它显示一个“使用MS登录”按钮,该按钮将触发MS登录。
- 这不起作用,因为
和[Authorize]
标记会立即将用户带到MS登录屏幕[AuthorizeForScopes]
- 这不起作用,因为
[Route("/")]
public class HomeController : Controller
{
[HttpGet]
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "Scopes")]
public IActionResult Index()
{
// We can't run the SPA on "/" because we need to intercept that here to require that the user is authorized before accessing the SPA.
return Redirect("/home");
}
}
重要中间件
// This is done AFTER useStaticFiles(), useEndpoints() and useSpaStaticFiles()
// Redirect the user to authenticate if the user isnt at this moment
// All static frontend related files are served using the UseSpaStaticFiles middleware
// What's left is the index.html
app.Use(async (context, next) =>
{
if (context.User?.Identity?.IsAuthenticated != true)
{
await context.ChallengeAsync(WellKnownAuthenticationSchemes.OpenIdConnect);
}
else
{
await next();
}
});
认证
//省略了其他一些身份验证配置;这不重要。
services.Configure(“Cookie”,opt=>
{
opt.Cookie.IsEssential=true;
opt.Cookie.Name=“auth”;
opt.Cookie.SameSite=SameSiteMode.Lax;//由于signin oidc回调的跨原点性质,需要此选项
opt.Cookie.SecurePolicy=Environment.IsDevelopment()
?CookieSecurePolicy.SameAsRequest
:厨师安全政策。始终;
opt.Cookie.HttpOnly=true;
opt.SlidingExpiration=true;
opt.ExpireTimeSpan=TimeSpan.FromDays(90);
});
服务。添加身份验证(“Cookie”);
服务
.AddMicrosoftIdentityWebAppAuthentication(配置、,
cookieScheme:“饼干”)
.EnableTokenAcquisitionTollDownstreamAPI(Configuration.GetValue(“Scopes”).Split(“”)
.AddDistributedTokenCaches();
因此,总结一下:
- 如果用户未登录/未授权可能在
上运行的作用域,我想显示一个自定义登录屏幕,然后按该页面上的按钮运行当前在/login
索引()上的
和[Authorize]
逻辑[AuthorizeForScopes]
- 我希望SPA在
上运行,并且只有在用户登录并授权了作用域后才能访问/
// Some other auth config is left out; it's not important.
services.Configure<CookieAuthenticationOptions>("Cookie", opt =>
{
opt.Cookie.IsEssential = true;
opt.Cookie.Name = "auth";
opt.Cookie.SameSite = SameSiteMode.Lax; // Required due to cross origin nature of signin-oidc callback
opt.Cookie.SecurePolicy = Environment.IsDevelopment()
? CookieSecurePolicy.SameAsRequest
: CookieSecurePolicy.Always;
opt.Cookie.HttpOnly = true;
opt.SlidingExpiration = true;
opt.ExpireTimeSpan = TimeSpan.FromDays(90);
});
services.AddAuthentication("Cookie");
services
.AddMicrosoftIdentityWebAppAuthentication(Configuration,
cookieScheme: "Cookie")
.EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("Scopes").Split(" "))
.AddDistributedTokenCaches();