Fal*_*noo 3 c# authentication blazor asp.net-core-3.1
我正在尝试从 Blazor 服务器网站检索 Azure AD 令牌,因此我可以将其添加为下游 API 服务中的授权标头。我能够在网站中设置 AAD 身份验证(效果非常好),但无法检索访问令牌,需要将其添加为下游 API 调用中的授权标头。
我在 .NET core 3.1 中使用 Blazor 服务器(所以不是 WebAssembly)
这是我当前的设置,但访问令牌始终为空,并且似乎无法修复它。任何帮助是极大的赞赏!
启动.cs
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options))
.AddCookie();
services.Configure<OpenIdConnectOptions>(AzureADDefaults.AuthenticationScheme, options =>
{
options.SaveTokens = true;
});
Run Code Online (Sandbox Code Playgroud)
_Host.cshtml
我添加了一个代码块并尝试从 HttpContext 检索 accessToken。然后我可以使用 app.razor 中的 CascadingValue 对象将该值传播到我的控制器。但是,access_token 始终为空。“User.Identity.IsAuthenticated”为 true,因此它正在进入我的 if 语句。
@{
string accessToken = null;
if (User.Identity.IsAuthenticated)
{
accessToken = await HttpContext.GetTokenAsync("access_token");
// accessToken is always empty :(
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里缺少什么?我能找到的有关此问题的大多数文章都是针对 Blazor WebAssembly
旁注:不确定这是否与此相关,但在我的控制器中,我能够获取 ClaimsPrincipal 对象。但我认为我无法从该对象获取不记名令牌(但认为这里值得一提)。
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
Run Code Online (Sandbox Code Playgroud)
我找到了这个问题的解决方案。我需要利用“Microsoft.Identity.Web”和“Microsoft.Identity.Web.UI”nuget 包才能检索令牌来调用 API。
我遵循以下示例中解释的解决方案: https: //github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/b07a9e06206f7274fdcadc34a50b8bebf9666fcf/4-WebApp-your-API/4-1-MyOrg #step-2-向您的 azure-active-directory-tenant 注册示例
我确实遇到了用户第一次登录时所需的同意机制的一些问题。这是通过添加“Microsoft 身份同意和条件访问处理程序服务”来解决的,其解释如下:https: //github.com/AzureAD /microsoft-identity-web/wiki/管理增量同意和条件访问
所以案件结案了:)
希望这对将来的人也有帮助。
为了完整起见,我添加了我在代码中所做的更改:
启动.cs
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(new string[] { Configuration["DashboardAPI:ApiScope"] })
.AddInMemoryTokenCaches();
services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
Run Code Online (Sandbox Code Playgroud)
API控制器类
在我的构造函数中注入“ITokenAcquisition”类并将其分配给“_tokenAcquisition”var 每次调用 API 时,我都会先执行“PrepareAuthenticatedClient”方法
private async Task PrepareAuthenticatedClient()
{
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { _dashboardAPIScope });
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
Run Code Online (Sandbox Code Playgroud)
在我调用 API 控制器的视图中,我添加了一个用于同意处理的 try-catch 块并注入同意处理程序
[Inject]
MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler { get; set; }
try
{
// Call to my API controller
}
catch(Exception ex)
{
ConsentHandler.HandleException(ex);
}
Run Code Online (Sandbox Code Playgroud)