3

基本的には自社用に作っている社員ポータルにSSOを実装しているのですが、グラフAPIにもアクセスできるようにしたいです(少なくとも、AzureAD REST APIの項目の追加/削除/取得など) SSO 経由でサインインする必要はありません。

このようにして、ある種の API キー/秘密のセットアップであると考えているものを使用して、何らかの方法で AD と対話する cron ジョブをスケジュールできます。技術的には、サインインして自分のアカウントをこれを実行するアカウントに設定することはできますが、それは一種のハッキーで信頼性が低いようです (たとえば、アカウントに何かが起こった場合、パスワードの有効期限が切れたり、変更されたりすると、更新トークンはもはや再度サインインする必要があり、タスクが一時的に中断される可能性があります。)

数か月前にこれを実装することを検討していたときに、これに関するドキュメントをどこかで見たことがあると断言できましたが、今では一生見つけることができません。

これが重複していないことを本当に願っています。検索する言葉遣いが思いつかないだけで、SSO ベースの API 情報が得られません。

更新 - わかりました、私はこれを理解したようです (以下に投稿された Shaun Luttin の回答の助けを借りて: https://stackoverflow.com/a/32618417/3721165 [便利なリンク])

ですから、ショーンがまとめてくれたすべての情報は本当に役に立ちました。当初、ドキュメントは、言葉遣いの仕方や、いくつかの例の複雑さのために、かなり混乱していました。しかし、いくつかの例に加えて、Shaun が提供した情報のいくつかを掘り下げ、自分でいくつかの実験/研究を行うと、これを思いつくことができました (基本的なデモ/概念):

using System;
using System.Globalization;
using System.Threading.Tasks;

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Azure.ActiveDirectory.GraphClient;


namespace AzureADGraphApi
{
    class Program
    {
        private static string tenant = "...tenant id...";
        private static string clientid = "...client id...";
        private static string appkey = "...app key...";
        private static string aadinstance = "https://login.microsoftonline.com/{0}";
        private static string graphResourceUrl = "https://graph.windows.net";

        static void Main(string[] args)
        {
            Uri serviceRoot = new Uri(graphResourceUrl + "/" + tenant);
            ActiveDirectoryClient adc = new ActiveDirectoryClient(serviceRoot, async () => await GetToken());

            IPagedCollection<IUser> Users = adc.Users.ExecuteAsync().Result;

            bool pagesLeft = false;
            do
            {
                foreach (IUser user in Users.CurrentPage)
                {
                    Console.WriteLine(user.DisplayName);
                }
                pagesLeft = Users.MorePagesAvailable;
                Users = Users.GetNextPageAsync().Result;
                Console.WriteLine("--- Page Break ---");
            } while (pagesLeft);
            Console.ReadLine();
        }

        private static async Task<string> GetToken()
        {
            AuthenticationContext authContext = new AuthenticationContext(String.Format(CultureInfo.InvariantCulture, aadinstance, tenant));
            AuthenticationResult result = authContext.AcquireToken(graphResourceUrl, new ClientCredential(clientid, appkey));
            return result.AccessToken;
        }
    }
}

さらなる調査の結果、Graph API を意図しとおりに使用するには、アプリ ID/ URL。

だから、私はショーンの答えを受け入れていますが、その答えの私の作業結果も伝えたかったのです。

助けてくれてありがとう、みんな!

4

2 に答える 2

16

必要なのは、シングル サインオンを行わないアクセス トークンです。Rick Rainey が提供したリンクから始められます。

を呼び出して、プログラムでアクセス トークンを取得できますAcquireTokenAsyncAcquireTokenAsync構築するアプリケーションのタイプと認証方法に応じて、さまざまな呼び出し方法があります。ネイティブ クライアント アプリケーションと Web アプリケーションのどちらを作成するかを決定する必要があります。

Web アプリケーションまたはネイティブ クライアント アプリケーション

アプリケーションの種類に基づいて、認証方法はかなり異なります。ユーザープロンプトなしで認証したい(つまり、ユーザー名/パスワードの入力を要求しない)ようです。以下は私にとってはうまくいき、ユーザープロンプトはまったく必要ありません。それらのそれぞれは、manage.windowsazure.com ポータルから取得する必要がある次の定数を使用します。それらを見つけるのに助けが必要な場合は、コメントでお知らせください。

private const string

    DIRECTORY_TENANT_NAME = "mytenant.onmicrosoft.com",
    DIRECTORY_TENANT_ID = "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx",
    RESOURCE_URL = "https://graph.windows.net",
    SUBSCRIPTION_ID = "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx",
    AUTHORITY = "https://login.microsoftonline.com/" + DIRECTORY_TENANT_NAME,

    // web application
    CLIENT_ID_WEB = "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx",
    CLIENT_SECRET_WEB = "xxxxxxxx/xxxxxxxxxxxx/xxxxxxxx/xxxxxxxx=",

    // native client application
    CLIENT_ID_NATIVE = "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx",

    // adminstrator
    USER_NAME = "myuser@mytenant.onmicrosoft.com",
    USER_PASSWORD = "xxxxxxxxxx";

トークンを取得するために、次の 3 つのオプションが開かれます (他にもあるかもしれませんが)。以下のそれぞれをテストしましたが、Azure Active Directory テナント、ユーザー、およびアプリケーションを適切に構成している限り、すべて機能します。

AcquireToken(文字列リソース、ClientAssertionCertificate clientCertificate)は Web Apps で動作します。このアプローチの欠点は、最初のセットアップ (PowerShell、証明書の作成) が難しいことです。利点は、一度設定すると使いやすいことです。ネイティブ クライアント アプリでは機能せず、次のエラーがスローされます。AADSTS50012: Client is public so a 'client_assertion' should not be presented.

var authContext = new AuthenticationContext(AUTHORITY);
var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certs = store
    .Certificates
    .Find(X509FindType.FindByIssuerName, "mvp2015", false);
var clientCertificate = new ClientAssertionCertificate(CLIENT_ID_WEB, certs[0]);
var result = authContext
    .AcquireTokenAsync(RESOURCE, clientCertificate)
    .Result;

AcquireToken(string resource, ClientCredential clientCredential)は Web Apps で動作します。設定が簡単で、一度設定すると使いやすいです。ネイティブ クライアント アプリは、クライアント シークレットがないため、このアプローチをサポートしていません。

var authContext = new AuthenticationContext(AUTHORITY);
var clientCredential = new ClientCredential(CLIENT_ID_WEB, CLIENT_SECRET_WEB);
var result = authContext
    .AcquireTokenAsync(RESOURCE, clientCredential)
    .Result;

AcquireToken(string resource, string clientId, UserCredential userCredential)は、ネイティブ クライアント アプリで動作します。Web Apps は次のエラーで失敗します: AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'.1 つの注意点は、ログインしているユーザーが Active Directory で正しく構成されている必要があることです。

var authContext = new AuthenticationContext(AUTHORITY);
var userCredential = new UserCredential(USER_NAME, USER_PASSWORD);
var result = authContext
    .AcquireTokenAsync(RESOURCE, CLIENT_ID_NATIVE, userCredential)
    .Result;

好みの方法でトークンを取得したら、次のように Active Directory グラフを使用できます。読みやすくするために、独自のメソッドにFunc入れることができますが、それは a にあります。accessTokenGetter

Func<Task<string>> accessTokenGetter = async () =>
{
    var authContext = new AuthenticationContext(AUTHORITY, false);
    var clientCredential = new ClientCredential(CLIENT_ID_WEB, CLIENT_SECRET_WEB);
    var result = await authContext
        .AcquireTokenAsync(RESOURCE_URL, clientCredential);
    var token = result.AccessToken;
    return token;
};

var uriRoot = new Uri(RESOURCE_URL);
var uriTenant = new Uri(uriRoot, DIRECTORY_TENANT_ID);
var client = new ActiveDirectoryClient(uriTenant, accessTokenGetter);
foreach (var u in client.Users.ExecuteAsync().Result.CurrentPage)
{
    var n = u.DisplayName;
}

備考

  • DIRECTORY_TENANT_ID、Azure Active Directory テナントのダッシュボードにいるときに、Web ブラウザーのアドレス バーにあります。manage.windowsazure.com > Active Directory > 一部のテナント。
  • Azure Active Directory 内にアプリケーションを作成したら、そのアクセス許可を構成する必要があります。これは、アプリケーションの CONFIGURE タブの下部にあります。manage.windowsazure.com > Active Directory > 一部のテナント > アプリケーション > 一部のアプリケーション > 構成。
  • 上記のデモでは、次の 2 つの NuGet パッケージを使用しています。
    • Microsoft.Azure.ActiveDirectory.GraphClientバージョン 2.1.0
    • Microsoft.IdentityModel.Clients.ActiveDirectoryバージョン 2.19.208020213

関連項目

ここに例があります: https://github.com/AzureADSamples/ConsoleApp-GraphAPI-DotNet

于 2015-09-16T20:49:50.150 に答える
0

Azure ADサービス プリンシパルは、あなたが求めているものだと私は信じています。アプリ用に作成する方法に関するドキュメントを次に示します。

https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/

于 2015-09-16T20:44:58.003 に答える