问题描述
我已经使用Visual Studio最新的 New Project 向导来创建一个ASP Core 2.0网页(剃刀页面),该页面使用个人帐户"作为我的身份验证选项.我已经创建了一个Azure AD B2C租户,并验证了它是否可以正常工作.
I have used Visual Studio's latest New Project wizard to create a ASP Core 2.0 Web page (Razor Pages) that uses Individual Accounts as my authentication option. I have created an Azure AD B2C tenant and validated that it works properly.
当我运行由向导创建的Web应用程序并单击右上角的登录时,它将重定向到我的Azure AD B2C网站,并且我可以正确登录.
When I run the web application that was created by the wizard and click Log In in the upper right, it redirects to my Azure AD B2C site, and I can properly login.
登录后,回调URL转到我的用户密码中配置的端点:
After login, the callback url goes to the endpoint configured in my user secrets:
...
"CallbackPath": "/signin-oidc",
...
这一切似乎都可以正常工作.我知道Azure AD B2C门户将令牌发送回上述/signin-oidc
回调路径并进行存储.
That all seems to work properly. I understand that the Azure AD B2C portal sends a token back to the above /signin-oidc
callback path and stores it.
如何获取该令牌的值?
我一直在遵循所有Azure AD B2C指南,但是并非所有指南都已更新到ASP Core 2.0,并且它们似乎都没有使用从15.4 VS向导生成的代码,例如:
I've been following all of the Azure AD B2C guides, but not all of them have been updated to ASP Core 2.0, and none of them seem to use the code generated from the 15.4 VS wizard such:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdB2C(options => Configuration.Bind("AzureAdB2C", options))
.AddCookie();
services.AddMvc();
}
注意:.AddAzureAdB2C(...)
没有B2C样本正在使用此功能,因此我很难理解.
None of the B2C samples are using this so its difficult for me to follow.
我的最终目标是获取令牌并将其用于我从Swagger使用Autorest生成的API类型的强类型类中,该API类需要令牌.
My end goal is to get the token and use that in a strongly-typed set of API classes I generated from Swagger using Autorest which require the token.
推荐答案
Azure AD B2C .Net Core示例概述了最佳方法,特别是针对Core 2.0的分支.
The best way to do this is outlined in the Azure AD B2C .Net Core sample, specifically the branch for Core 2.0.
在正常模型/流中,您的应用程序将获得id_token和授权码,但不会获得令牌.您的中间层需要将授权代码交换为令牌.该令牌就是您要发送到Web API的令牌.
In the normal model/flow, your application will get an id_token and an authorization code but not a token. The authorization code needs to be exchanged for a token by your middle tier. This token is what you'd then be sending over to your web API.
执行此操作的方法涉及以下内容:
The way to do this involves the following:
- 确保您的中间层正在为您的主要策略请求id_token + code(您不想为您的编辑配置文件或密码重置策略执行此操作).从样本的 OpenIdConnectOptionsSetup.cs#L77 :
public Task OnRedirectToIdentityProvider(RedirectContext context)
{
var defaultPolicy = AzureAdB2COptions.DefaultPolicy;
if (context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty, out var policy) &&
!policy.Equals(defaultPolicy))
{
context.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile;
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower().Replace(defaultPolicy.ToLower(), policy.ToLower());
context.Properties.Items.Remove(AzureAdB2COptions.PolicyAuthenticationProperty);
}
else if (!string.IsNullOrEmpty(AzureAdB2COptions.ApiUrl))
{
context.ProtocolMessage.Scope += $" offline_access {AzureAdB2COptions.ApiScopes}";
// -----------------------------
// THIS IS THE IMPORTANT PART:
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.CodeIdToken;
// -----------------------------
}
return Task.FromResult(0);
}
- 将代码交换为令牌.来自样本的 OpenIdConnectOptionsSetup.cs#L103-L124 :
public async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
{
// Use MSAL to swap the code for an access token
// Extract the code from the response notification
var code = context.ProtocolMessage.Code;
string signedInUserID = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, context.HttpContext).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
try
{
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, AzureAdB2COptions.ApiScopes.Split(' '));
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
catch (Exception ex)
{
//TODO: Handle
throw;
}
}
- 然后您可以在代码的其他地方使用此令牌来调用API.从样本的 HomeController.cs#L45-L57 :
var scope = AzureAdB2COptions.ApiScopes.Split(' ');
string signedInUserID = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, this.HttpContext).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
AuthenticationResult result = await cca.AcquireTokenSilentAsync(scope, cca.Users.FirstOrDefault(), AzureAdB2COptions.Authority, false);
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdB2COptions.ApiUrl);
// Add token to the Authorization header and make the request
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = await client.SendAsync(request);
这篇关于如何获取ASP Core 2.0中从Azure AD B2C返回的令牌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!