ユーザーに代わってAzureアプリケーションを登録する必要があります。Azure Graph API を使用して、次のアクションを実行しました。
- 必要なリソースを使用してアプリケーションを作成する
- 登録済みアプリのサービス プリンシパルを作成する
- 必要なスコープを持つサービス プリンシパルのOAuth2PermissionGrant エンティティを作成する
その後、作成したuppのaccess_tokenの取得に成功しました。しかし残念ながら、そのトークンで O365 リソースにアクセスしようとすると、401 Unauthorized が返されました。JSON化されたエラーなし!!
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
プラグマ: no-cache
Content-Length: 0
Expires: -1
Server: Microsoft-IIS/8.5
Server: Microsoft-IIS/8.5
WWW-Authenticate: Bearer
X-AspNet-Version : 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
日付: 2015 年 12 月 10 日 (木) 11:58:59 GMT... それでおしまい!
次に Azure portal に移動しましたが、すべて問題ありませんでした。いくつかの実験の後、ポータルを介した変更後 (表面的なものであっても)、access_token が有効になることに気付きました。
そこで、JWT デコーダーを使用してトークンを比較したところ、スコープが含まれていないことがわかりました。
また、変更後に OAuth2PermissionGrant エンティティが上書きされていることに気付きました。
次の Web リソースとライブラリを使用しました。
- 承認用ライブラリ:ADAL
- グラフ API にアクセスするためのライブラリ: www.nuget.org/packages/Microsoft.Azure.ActiveDirectory.GraphClient
- GraphClient の例の完全なリストは、github.com/Azure-Samples/active-directory-dotnet-graphapi-console/blob/master/GraphConsoleAppV3/Program.cs にあります。
以下に、プログラムでアプリを作成するコードを添付しました。また、フィドラーのログやその他の情報を添付することもできます。
ActiveDirectoryClient activeDirectoryClient;
string clientSecret = "...hidden...";
string name = "O365 auto created client";
try
{
activeDirectoryClient = AuthenticationHelper.GetActiveDirectoryClientAsUser();
var appObject = new Application
{
DisplayName = "O365 auto created client",
Homepage = "https://sign",
LogoutUrl = "http://logout1.net"
};
appObject.IdentifierUris.Add("https://localhost/demo/" + Guid.NewGuid());
appObject.ReplyUrls.Add("https://localhost/demo");
var officeAccess = new RequiredResourceAccess
{
ResourceAppId = "c5393580-f805-4401-95e8-94b7a6ef2fc2", // OfficeManagePlatform
ResourceAccess = new List<ResourceAccess>
{
new ResourceAccess
{
Id = new Guid("825c9d21-ba03-4e97-8007-83f020ff8c0f"),
Type = "Role,Scope"
},
new ResourceAccess
{
Id = new Guid("e2cea78f-e743-4d8f-a16a-75b629a038ae"),
Type = "Role,Scope"
},
new ResourceAccess
{
Id = new Guid("594c1fb6-4f81-4475-ae41-0c394909246c"),
Type = "Role,Scope"
}
}
};
appObject.RequiredResourceAccess.Add(officeAccess);
var passCreds = new PasswordCredential
{
StartDate = DateTime.UtcNow,
EndDate = DateTime.UtcNow.AddYears(1),
Value = clientSecret,
KeyId = null,
CustomKeyIdentifier = null
};
appObject.PasswordCredentials.Add(passCreds);
try
{
await activeDirectoryClient.Applications.AddApplicationAsync(appObject);
}
catch (Exception e)
{
Console.WriteLine("Application Creation exception: {0} {1}", e.Message,
e.InnerException != null ? e.InnerException.Message : "");
}
ServicePrincipal newServicePrincpal = new ServicePrincipal();
if (appObject!= null && appObject.AppId != null)
{
newServicePrincpal.DisplayName = appObject.DisplayName;
newServicePrincpal.AccountEnabled = true;
newServicePrincpal.AppId = appObject.AppId;
newServicePrincpal.Tags.Add("WindowsAzureActiveDirectoryIntegratedApp");
try
{
activeDirectoryClient.ServicePrincipals.AddServicePrincipalAsync(newServicePrincpal).Wait();
Console.WriteLine("New Service Principal created: " + newServicePrincpal.ObjectId);
}
catch (Exception e)
{
Console.WriteLine("Service Principal Creation execption: {0} {1}", e.Message,
e.InnerException != null ? e.InnerException.Message : "");
}
}
OAuth2PermissionGrant permissionObject = new OAuth2PermissionGrant();
permissionObject.ConsentType = "AllPrincipals";
permissionObject.Scope = "ServiceHealth.Read";
permissionObject.StartTime = DateTime.MinValue;
permissionObject.ExpiryTime = (DateTime.Now).AddMonths(12);
// resourceId is objectId of the resource manage.office.com // in this case objectId of AzureAd (Graph API)
permissionObject.ResourceId = "52f62a75-b73d-496a-9bfa-1bf41339a90a"; // "52620afb-80de-4096-a826-95f4ad481686";
//ClientId = objectId of servicePrincipal
permissionObject.ClientId = newServicePrincpal.ObjectId;
try
{
activeDirectoryClient.Oauth2PermissionGrants.AddOAuth2PermissionGrantAsync(permissionObject).Wait();
Console.WriteLine("New Permission object created: " + permissionObject.ObjectId);
}
catch (Exception e)
{
Console.WriteLine("Permission Creation exception: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : "");
}
return new ClientCredential(clientId: appObject.AppId, clientSecret: clientSecret);
}
catch (Exception ex)
{
return null;
}