无法使用客户端ID和密码

时间:2016-05-01 14:57:29

标签: c# azure office365 azure-active-directory microsoft-graph

我正在尝试使用Unified API(Microsoft.Graph 1.0.1)来访问我的用户个人资料照片,但访问照片时我只收到以下错误:

  

代码:ErrorAccessDenied
  消息:访问被拒绝。检查凭据,然后重试。

访问/列出其他用户个人资料数据工作正常,我的应用程序被添加为"公司管理员"通过PowerShell并在管理门户中设置所有权限。当我使用我的管理员用户登录的GraphExlorer时,它也可以正常工作。也通过" old" Azure Active Directory图谱API我可以读取/写入用户缩略图照片,但这不是Office 365中显示的那个。

如何获取相应的访问权限以对用户个人资料照片执行操作?

这是我使用的代码(缩写为相关部分):

class Program
{
    private const string authStringMicrosoft = "https://login.microsoftonline.com/MY_APP_ID/";

    private const string clientID = "MY_CLIENT_ID";
    private const string clientSecret = "MY_CLIENT_SECRET";

    private const string graphResourceId = "https://graph.microsoft.com";

    static void Main(string[] args)
    {
        AsyncContext.Run(RunAsync);

        Console.WriteLine("DONE");
        Console.ReadLine();
    }

    private static async Task RunAsync()
    {
        var token = await GetAppTokenAsync(authStringMicrosoft, graphResourceId);
        var authHelper = new AuthenticationHelper() { AccessToken = token }
        var graphClient = new GraphServiceClient(authHelper);
        await ListUser(graphClient);
    }

    private static async Task ListUser(GraphServiceClient graphClient)
    {
        Console.WriteLine("User-List:");
        var users = await graphClient.Users.Request().GetAsync();
        foreach (var user in users)
        {
            Console.WriteLine($"{user.UserPrincipalName}:\t\t{user.GivenName} {user.Surname}");
            if (user.UserPrincipalName == "USER_WITH_PICTURE")
            {
                var graphUser = graphClient.Users[user.UserPrincipalName];
                var graphPhoto = graphUser.Photo;

                var photoInfo = await graphPhoto.Request().GetAsync(); // <= here the exceptions is thrown
                Console.WriteLine($"{photoInfo.Id}:\t{photoInfo.Width}x{photoInfo.Height}");

                var photoStream = await graphPhoto.Content.Request().GetAsync();

                byte[] photoByte = new byte[photoStream.Length];
                photoStream.Read(photoByte, 0, (int)photoStream.Length);
                File.WriteAllBytes(@"D:\User.jpg", photoByte);
            }
        }
    }

    private static async Task<string> GetAppTokenAsync(string authority, string azureGraphAPI)
    {
        var authenticationContext = new AuthenticationContext(authority);
        var clientCred = new ClientCredential(clientID, clientSecret);
        var authenticationResult = await authenticationContext.AcquireTokenAsync(azureGraphAPI, clientCred);
        return authenticationResult.AccessToken;
    }
}

public class AuthenticationHelper : IAuthenticationProvider
{
    public string AccessToken { get; set; }

    public Task AuthenticateRequestAsync(HttpRequestMessage request)
    {
        request.Headers.Add("Authorization", "Bearer " + AccessToken);
        return Task.FromResult(0);
    }
}

我使用以下NuGet包:

<packages>
  <package id="Microsoft.Data.Edm" version="5.7.0" targetFramework="net46" />
  <package id="Microsoft.Data.OData" version="5.7.0" targetFramework="net46" />
  <package id="Microsoft.Data.Services.Client" version="5.7.0" targetFramework="net46" />
  <package id="Microsoft.Graph" version="1.0.1" targetFramework="net46" />
  <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.24.304111323" targetFramework="net46" />
  <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net46" />
  <package id="Nito.AsyncEx" version="3.0.1" targetFramework="net46" />
  <package id="System.Spatial" version="5.7.0" targetFramework="net46" />
</packages>

这是一个传递错误的示例请求(使用带有从上面的应用程序中读出的令牌的邮递员):

  

GET /v1.0/users/MY_USER_WITH_PHOTO/photo/ HTTP / 1.1
  主持人:graph.microsoft.com
  连接:保持活力
  授权:bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1 ...
  缓存控制:无缓存
  用户代理:Mozilla / 5.0(Windows NT 6.3; WOW64)AppleWebKit / 537.36(KHTML,与Gecko一样)Chrome / 49.0.2623.112 Safari / 537.36
  邮差 - 令牌:e756a8a3-22e2-d40c-8e52-15c4d1aa7468
  接受: /
  Accept-Encoding:gzip,deflate,sdch
  Accept-Language:de,en-US; q = 0.8,en; q = 0.6

回复:

  

HTTP / 1.1 403禁止
  缓存控制:私人
  转移编码:分块
  内容类型:application / json
  服务器:Microsoft-IIS / 8.5
  request-id:96e8dda8-2353-4891-8c42-99cfe7e22887
  client-request-id:96e8dda8-2353-4891-8c42-99cfe7e22887
  x-ms-ags-diagnostic:{&#34; ServerInfo&#34;:{&#34; DataCenter&#34;:&#34; North Europe&#34;,&#34; Slice&#34;:&#34 ; SliceA&#34;&#34; ScaleUnit&#34;:&#34; 001&#34;&#34;主机&#34;:&#34; AGSFE_IN_4&#34;&#34; ADSiteName&#34; :&#34; DUB&#34;}}   持续时间:1367.7691
  X-Powered-By:ASP.NET
  日期:太阳,2016年5月1日17:57:02 GMT

体:

  

{
   &#34;错误&#34;:{
     &#34;代码&#34;:&#34; ErrorAccessDenied&#34;,
     &#34;消息&#34;:&#34;访问被拒绝。检查凭据,然后重试。&#34;,      &#34; innerError&#34;:{
       &#34; request-id&#34;:&#34; 96e8dda8-2353-4891-8c42-99cfe7e22887&#34;,
       &#34; date&#34;:&#34; 2016-05-01T17:57:02&#34;
     }
   }
  }

同样,如果我从请求中删除/photo,我会毫无问题地获得所有常见的用户详细信息。

这里是我的应用程序(web-app)的权限: permissions

这是一个解密的访问令牌:

{
 typ: "JWT",
 alg: "RS256",
 x5t: "MnC_VZcATfM5pOYiJHMba9goEKY",
 kid: "MnC_VZcATfM5pOYiJHMba9goEKY"
}.
{
 aud: "https://graph.microsoft.com",
 iss: "https://sts.windows.net/11205e59-fa81-480f-b497-571579c5389a/",
 iat: 1462795409,
 nbf: 1462795409,
 exp: 1462799309,
 appid: "c34a87ef-352a-4af4-a166-eb7e521a0ec9",
 appidacr: "1",
 idp: "https://sts.windows.net/11205e59-fa81-480f-b497-571579c5389a/",
 oid: "1db8c6b5-10ba-40ac-bbff-86ab440c4fd3",
 roles: [
  "Mail.ReadWrite",
  "Device.ReadWrite.All",
  "User.ReadWrite.All",
  "Calendars.Read",
  "Group.Read.All",
  "Directory.ReadWrite.All",
  "Contacts.ReadWrite",
  "Group.ReadWrite.All",
  "Directory.Read.All",
  "User.Read.All",
  "Mail.Read",
  "Calendars.ReadWrite",
  "Mail.Send",
  "MailboxSettings.ReadWrite",
  "Contacts.Read"
 ],
 sub: "1db8c6b5-10ba-40ac-bbff-86ab440c4fd3",
 tid: "11205e59-fa81-480f-b497-571579c5389a",
 ver: "1.0"
}

1 个答案:

答案 0 :(得分:0)

以防其他人在收到错误时读取此内容。我在创建自己的graphClient时遇到了同样的错误,我得到它的原因是由于使用非管理员帐户...

var users = await graphClient.Users.Request().Select().GetAsync();

使用非管理员帐户,您只能访问一些基本属性,如姓氏,名字等 - 这对我有用...

var users = await graphClient.Users.Request().Select("mail,givenName,surname").GetAsync();