我是多租户应用程序的新手,已经搜索了几天关于如何在 .NET Core 2.1 中本地获取access_token的信息。到目前为止,我发现的所有内容都是2.0或更早的版本,而2.1中都不存在发布的方法。
我已经创建了一个Microsoft Graph帮助程序,该帮助程序使用字符串access_token
,并将获取用户详细信息。接收授权码(OnAuthorizationCodeReceived事件)后,我只是尝试用access_token
调用帮助程序。
我觉得这最多应该是一个单行代码或简短代码段,而且我似乎找不到解决方法。
这是我希望在其中进行的Azure AD扩展:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Authentication
{
public static class AzureAdAuthenticationBuilderExtensions
{
public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder)
=> builder.AddAzureAd(_ => { });
public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
{
builder.Services.Configure(configureOptions);
builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();
builder.AddOpenIdConnect();
return builder;
}
private class ConfigureAzureOptions: IConfigureNamedOptions<OpenIdConnectOptions>
{
private readonly AzureAdOptions _azureOptions;
public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
{
_azureOptions = azureOptions.Value;
}
public void Configure(string name, OpenIdConnectOptions options)
{
options.ClientId = _azureOptions.ClientId;
options.Authority = $"{_azureOptions.Instance}";
options.UseTokenLifetime = true;
options.CallbackPath = _azureOptions.CallbackPath;
options.RequireHttpsMetadata = true;
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.TokenValidationParameters.ValidateIssuer = true;
options.TokenValidationParameters.IssuerValidator = ValidateIssuer;
options.Events.OnAuthenticationFailed = AuthenticationFailed;
options.Events.OnAuthorizationCodeReceived = AuthorizationCodeReceived;
}
// TODO check tenant against database for authorized tenants
private string ValidateIssuer(string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters)
{
if (false)
{
//throw new SecurityTokenInvalidIssuerException();
// how do i get my db context here if there's no context in the scope?
// var db = context.HttpContext.RequestServices.GetRequiredService<RdmsContext>(); <-- something like this
}
// allowed
return issuer;
}
private static Task AuthenticationFailed(
AuthenticationFailedContext context)
{
context.HandleResponse();
string message = Uri.EscapeUriString(context.Exception.Message);
context.Response.Redirect($"/Home/Error?message={message}");
return Task.CompletedTask;
}
private static async Task AuthorizationCodeReceived(
AuthorizationCodeReceivedContext context)
{
string authorizationCode = context.ProtocolMessage.Code;
string idToken = context.ProtocolMessage.IdToken;
// ProtocolMessage has AccessToken property, but it's null.
// Exchange authorization code for access_token here
string accessToken = ...
var userDetails = MyProject.Helpers.Graph
.GetUserDetailsAsync(accessToken);
context.HandleCodeRedemption(accessToken, idToken);
}
public void Configure(OpenIdConnectOptions options)
{
Configure(Options.DefaultName, options);
}
}
}
}
答案 0 :(得分:1)
经过反复的 次尝试,我终于找到了缺失的部分。
首先,我将options.ResponseType
更改为OpenIdConnectResponseType.IdTokenToken
,据我了解它返回一个IdToken和一个Token(访问令牌)。这需要提供一个将使用访问令牌的资源。
因此,我还添加了options.Resource
,其值为"https://graph.microsoft.com"
。
我还删除了options.GetClaimsFromUserInfoEndpoint = true;
我还必须在Azure中更新应用程序清单,以将oauth2AllowImplicitFlow
更改为true
。
最后,我将OnAuthorizationCodeRecevied
事件OnTokenValidated
替换为调用Microsoft Graph帮助程序的位置。
这些更改的组合导致成功接收访问令牌,然后我可以将其提供给Microsoft Graph帮助程序并获得所需的信息。
最终的Configure
方法现在看起来像这样:
public void Configure(string name, OpenIdConnectOptions options)
{
options.ClientId = _azureOptions.ClientId;
options.Resource = "https://graph.microsoft.com";
options.Authority = $"{_azureOptions.Instance}";
options.UseTokenLifetime = true;
options.CallbackPath = _azureOptions.CallbackPath;
options.RequireHttpsMetadata = true;
options.ResponseType = OpenIdConnectResponseType.IdTokenToken;
options.SaveTokens = true;
options.TokenValidationParameters.ValidateIssuer = true;
options.TokenValidationParameters.IssuerValidator = ValidateIssuer;
options.Events.OnAuthenticationFailed = AuthenticationFailed;
options.Events.OnTokenValidated = TokenValidatedAsync;
}
并且TokenValidatedAsync
现在在TokenValidatedContext.ProtocolMessage.AccessToken
中找到了访问令牌:
private static async Task TokenValidatedAsync(
TokenValidatedContext context)
{
string accessToken = context.ProtocolMessage.AccessToken;
Graph.User userDetails = await MyProject.Helpers.Graph
.GetUserDetailsAsync(accessToken);
}
在这里,我可以使用Microsoft Graph用户详细信息来完成我需要做的事情。
我找不到任何可行的示例,因此将其留在此处以供将来参考。
答案 1 :(得分:0)
非常感谢,我想知道如何获取Microsoft图形的access_token,但是我使用的是Microsoft.AspNetCore.Authentication.AzureAD.UI(抽象了所有OpenId配置),我认为options.UseTokenLifetime = true
和options.SaveTokens = true;
帮助访问了context.ProtocolMessage.AccessToken
再次感谢您