我必须代表用户注册 azure 应用程序。我使用 Azure Graph API 执行以下操作:
- 创建具有所需资源的应用程序
- 为注册的应用程序创建服务主体
- 为具有所需范围的服务主体创建OAuth2PermissionGrant 实体
之后,我成功获得了创建 upp 的 access_token。但不幸的是,当我尝试使用该令牌访问 O365 资源时,返回了 401 Unauthorized。没有任何 json 错误!!
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: 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
日期: Thu, 10 Dec 2015 11:58:59 GMT... 而已!
接下来我去了 Azure 门户 - 一切正常。经过几次实验后,我注意到 access_token 在通过门户(甚至是外观)进行任何更改后变得有效。
所以我使用 JWT 解码器比较了令牌,发现没有包含 Scopes:
我还注意到 OAuth2PermissionGrant 实体在更改后被覆盖。
我使用了以下网络资源和库:
- 授权库:ADAL
- 用于访问 Graph 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;
}