web-dev-qa-db-ja.com

.Net Core 2.0-MicrosoftGraphで使用するAADアクセストークンを取得します

AzureAD認証を使用して新しい.NetCore 2.0プロジェクトを起動すると、テナントにサインインできる実用的なサンプルが得られます。

サインインしたユーザーのアクセストークンを取得し、それを使用してMicrosoft GraphAPIを操作したいと思います。

これを実現する方法に関するドキュメントが見つかりません。新しい.NETCore 2.0プロジェクトの開始時に作成されたテンプレートを使用して、アクセストークンを取得し、グラフAPIにアクセスする簡単な方法が必要です。そこから私は残りを理解することができるはずです。

VisualStudioで新しい2.0MVC Coreアプリを作成するときに、認証用に職場と学校のアカウントを選択するプロセスに従うときに作成されるプロジェクトで機能することが非常に重要です。

7
Green_qaue

その方法を示すブログ記事を書きました: ASP.NET Core 2.0 Azure AD認証

TL; DRは、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)であり、他の設定(クライアントIDなど)とともにconfigからバインドしています。

ADALを使用してトークンを引き換え、結果のトークンをトークンキャッシュに保存します。

トークンキャッシュは作成する必要があるものです。これが サンプルアプリ の例です。

_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;
        }
    }
}
_

ここでのトークンキャッシュは、分散キャッシュを使用してトークンを保存するため、アプリにサービスを提供するすべてのインスタンスがトークンにアクセスできます。これらはユーザーごとにキャッシュされるため、後で任意のユーザーのトークンを取得できます。

次に、トークンを取得してMSグラフを使用する場合は、次のようにします(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;
    }
}
_

そこで、(トークンキャッシュを使用して)サイレントにトークンを取得し、それをグラフへのリクエストに添付します。

13
juunas