問(wèn)題描述
使用 Azure AD 身份驗(yàn)證啟動(dòng)新的 .Net Core 2.0 項(xiàng)目時(shí),您會(huì)獲得一個(gè)可以登錄租戶的工作示例,太棒了!
When starting up a fresh .Net Core 2.0 project with Azure AD Authentication you get a working sample that can sign in to your tenant, great!
現(xiàn)在我想獲取已登錄用戶的訪問(wèn)令牌,并使用它與 Microsoft Graph API 一起工作.
Now I want to get an access token for the signed in user and use that to work with Microsoft Graph API.
我沒(méi)有找到任何關(guān)于如何實(shí)現(xiàn)這一點(diǎn)的文檔.我只想要一種簡(jiǎn)單的方法來(lái)獲取訪問(wèn)令牌并訪問(wèn)圖形 API,使用啟動(dòng)新 .NET Core 2.0 項(xiàng)目時(shí)創(chuàng)建的模板.從那里我應(yīng)該能夠弄清楚其余的.
I am not finding any documentation on how to achieve this. I just want a simple way to get an access token and access the graph API, using the template created when you start a new .NET Core 2.0 project. From there I should be able to figure out the rest.
在 Visual Studio 中創(chuàng)建新的 2.0 MVC Core 應(yīng)用程序時(shí),它適用于在執(zhí)行選擇工作和學(xué)校帳戶進(jìn)行身份驗(yàn)證的過(guò)程時(shí)創(chuàng)建的項(xiàng)目.
Very important that it works with the project that gets created when following the process where you select Work and school accounts for authentication when creating a new 2.0 MVC Core app in Visual Studio.
推薦答案
我寫了一篇博客文章,展示了如何做到這一點(diǎn):ASP.NET Core 2.0 Azure AD 身份驗(yàn)證
I wrote a blog article which shows just how to do that: ASP.NET Core 2.0 Azure AD Authentication
TL;DR 是當(dāng)您收到來(lái)自 AAD 的授權(quán)代碼時(shí),您應(yīng)該添加這樣的處理程序:
The TL;DR is that you should add a handler like this for when you receive an authorization code from AAD:
.AddOpenIdConnect(opts =>
{
Configuration.GetSection("Authentication").Bind(opts);
opts.Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = async ctx =>
{
var request = ctx.HttpContext.Request;
var currentUri = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path);
var credential = new ClientCredential(ctx.Options.ClientId, ctx.Options.ClientSecret);
var distributedCache = ctx.HttpContext.RequestServices.GetRequiredService<IDistributedCache>();
string userId = ctx.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var cache = new AdalDistributedTokenCache(distributedCache, userId);
var authContext = new AuthenticationContext(ctx.Options.Authority, cache);
var result = await authContext.AcquireTokenByAuthorizationCodeAsync(
ctx.ProtocolMessage.Code, new Uri(currentUri), credential, ctx.Options.Resource);
ctx.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
};
});
這里我的 context.Options.Resource
是 https://graph.microsoft.com
(Microsoft Graph),我從配置和其他設(shè)置綁定(客戶 ID 等).
Here my context.Options.Resource
is https://graph.microsoft.com
(Microsoft Graph), which I'm binding from config along with other settings (client id etc.).
我們使用 ADAL 兌換令牌,并將生成的令牌存儲(chǔ)在令牌緩存中.
We redeem a token using ADAL, and store the resulting token in a token cache.
令牌緩存是你必須要做的事情,這是示例應(yīng)用程序中的示例:
The token cache is something you will have to make, here is the example from the example app:
public class AdalDistributedTokenCache : TokenCache
{
private readonly IDistributedCache _cache;
private readonly string _userId;
public AdalDistributedTokenCache(IDistributedCache cache, string userId)
{
_cache = cache;
_userId = userId;
BeforeAccess = BeforeAccessNotification;
AfterAccess = AfterAccessNotification;
}
private string GetCacheKey()
{
return $"{_userId}_TokenCache";
}
private void BeforeAccessNotification(TokenCacheNotificationArgs args)
{
Deserialize(_cache.Get(GetCacheKey()));
}
private void AfterAccessNotification(TokenCacheNotificationArgs args)
{
if (HasStateChanged)
{
_cache.Set(GetCacheKey(), Serialize(), new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1)
});
HasStateChanged = false;
}
}
}
這里的令牌緩存使用分布式緩存來(lái)存儲(chǔ)令牌,以便為您的應(yīng)用提供服務(wù)的所有實(shí)例都可以訪問(wèn)令牌.它們按用戶緩存,因此您可以稍后為任何用戶檢索令牌.
The token cache here uses a distributed cache to store tokens, so that all instances serving your app have access to the tokens. They are cached per user, so you can retrieve a token for any user later.
然后,當(dāng)您想要獲取令牌并使用 MS 圖時(shí),您會(huì)執(zhí)行類似(GetAccessTokenAsync()
中的重要內(nèi)容):
Then when you want to get a token and use MS graph, you'd do something like (important stuff in GetAccessTokenAsync()
):
[Authorize]
public class HomeController : Controller
{
private static readonly HttpClient Client = new HttpClient();
private readonly IDistributedCache _cache;
private readonly IConfiguration _config;
public HomeController(IDistributedCache cache, IConfiguration config)
{
_cache = cache;
_config = config;
}
[AllowAnonymous]
public IActionResult Index()
{
return View();
}
public async Task<IActionResult> MsGraph()
{
HttpResponseMessage res = await QueryGraphAsync("/me");
ViewBag.GraphResponse = await res.Content.ReadAsStringAsync();
return View();
}
private async Task<HttpResponseMessage> QueryGraphAsync(string relativeUrl)
{
var req = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0" + relativeUrl);
string accessToken = await GetAccessTokenAsync();
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return await Client.SendAsync(req);
}
private async Task<string> GetAccessTokenAsync()
{
string authority = _config["Authentication:Authority"];
string userId = User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var cache = new AdalDistributedTokenCache(_cache, userId);
var authContext = new AuthenticationContext(authority, cache);
string clientId = _config["Authentication:ClientId"];
string clientSecret = _config["Authentication:ClientSecret"];
var credential = new ClientCredential(clientId, clientSecret);
var result = await authContext.AcquireTokenSilentAsync("https://graph.microsoft.com", credential, new UserIdentifier(userId, UserIdentifierType.UniqueId));
return result.AccessToken;
}
}
我們?cè)诖颂庫(kù)o默獲取令牌(使用令牌緩存),并將其附加到對(duì) Graph 的請(qǐng)求中.
There we acquire a token silently (using the token cache), and attach it to requests to the Graph.
這篇關(guān)于.Net Core 2.0 - 獲取 AAD 訪問(wèn)令牌以與 Microsoft Graph 一起使用的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!