我认为我的主要问题是我应该使用哪个身份验证流程 - 代表或隐式授权流程?但是,我设置的身份验证和授权Startup.cs
可能是错误的,而且我还差得很远,如果是这样,我深表歉意。
我在 Azure 中有一个现有的 Angular SPA 和一个也在 Azure 中运行的 Net Framework API。
Web API 已移植到 Net Core 3.1。
在我们的 Azure 目录中,我有两个已注册的应用程序。一个用于 API,另一个用于 SPA。我已经在 WEB API 的授权客户端下添加了 SPA 客户端 ID。
值得注意的是,App 服务实际上是在不同的目录中运行(我认为这很好但只是提一下)
这是 Azure AD 中的相关身份验证/授权设置。
private void ConfigureAzureAD(IServiceCollection services, IMvcBuilder mvcBuilder)
{
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = true;
});
mvcBuilder.AddMvcOptions(options =>
{
var policy = new AuthorizationPolicyBuilder().
RequireAuthenticatedUser().
Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).
SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseResponseCaching();
}
app.UseStaticFiles();
app.UseCors(CORS_POLICY);
if (UseAzureAD)
{
app.UseHttpsRedirection();
}
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthorization();
app.UseAuthentication();
app.UseMvc();
}
我可以直接成功使用 API 并进行身份验证。
SPA 正在使用 Angular ADAL。如果我没看错的话,它不适用于 Microsoft Identity V2 端点。- 我们仍然需要升级到 MSAL,尽管我仍然无法理解最终的身份验证流程(我认为这是我的主要问题)。
目前,如果我点击 SPA,它将只使用当前的 ADAL 配置进行身份验证,但是当它点击 API 时,会被重定向到https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/authorize?
带有 ID Token 的位置。
它挂在重定向上,并且它们是 CORS 错误,因为来源为空。我知道这是预期的,因为 SPA 配置不正确。
API 确实调用 MS Graph API 来为用户获取组(但使用客户端 ID 和客户端密码来获取访问令牌来调用 MS Graph),所以我认为这并不意味着我需要使用 On-Behalf -Of-Flow(我确实看到这篇文章Authenticating against Microsoft Graph with SPA and then using token in Web API)?
我已经查看了这个示例https://github.com/Azure-Samples/ms-identity-javascript-angular-spa-aspnetcore-webapi以了解隐式授权流程。
我确实注意到该示例中的身份验证方案是JwtBearerDefualts
有意义的,因为 ID 令牌是 JWT,所以这让我质疑我的 API 启动配置。
这是在 API 中调用 MS Graph 的位,它可能需要最好地回答我应该使用 2 个流中的哪一个(它再次获得带有客户端密码的访问令牌)。
private async Task<IReadOnlyCollection<string>> LoadReportGroupsCurrentUserCanRead()
{
var objectID = claimsPrincipal
.Claims
.FirstOrDefault(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier")
?.Value;
var graphServiceClient = await GetGraphServiceClient();
var groups = await graphServiceClient
.Groups
.Request()
.GetAsync();
var memberGroups = await graphServiceClient
.Users[objectID]
.GetMemberGroups(true)
.Request()
.PostAsync();
return memberGroups.Select(mg => groups.SingleOrDefault(g => g.Id == mg))
.Where(g => g?.DisplayName?.EndsWith(" Report Group", StringComparison.InvariantCultureIgnoreCase) == true)
.Select(g => g.Description)
.Where(name => !string.IsNullOrWhiteSpace(name))
.ToArray();
}
private async Task<GraphServiceClient> GetGraphServiceClient()
{
string authority = new Uri(microsoftLogin, tenantID).AbsoluteUri;
var authenticationContext = new AuthenticationContext(authority);
var clientCredential = new ClientCredential(clientID, clientSecret);
var authenticationResult = await authenticationContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential);
var authProvider = new DelegateAuthenticationProvider(requestMessage =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authenticationResult.AccessToken);
return Task.CompletedTask;
});
return new GraphServiceClient(authProvider);
}
最后,我认为我们的 SPA 使用的 Angular 版本不支持 Angular MSAL。我可以只使用 Vanilla MSAL JS(认为我们现在没有时间升级 Angular)吗?