2017-07-15 152 views
2

我有一个天蓝色的多租户应用程序。我可以登录并获取用户姓名和电子邮件等基本信息。从Azure获取用户个人资料图片

现在我需要从azure获取用户的个人资料图片。 我尝试了一些在互联网上提供的解决方案,但他们都没有为我工作。

这里是我的Startup.Auth.cs代码

public partial class Startup 
    { 
     private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; 
     private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"]; 
     private string graphResourceID = "https://graph.windows.net"; 
     private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"]; 
     private string authority = aadInstance + "common"; 
     private ApplicationDbContext db = new ApplicationDbContext(); 

     public void ConfigureAuth(IAppBuilder app) 
     { 

      app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 

      app.UseCookieAuthentication(new CookieAuthenticationOptions { }); 

      app.UseOpenIdConnectAuthentication(
       new OpenIdConnectAuthenticationOptions 
       { 
        ClientId = clientId, 
        Authority = authority, 
        TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters 
        { 
         // instead of using the default validation (validating against a single issuer value, as we do in line of business apps), 
         // we inject our own multitenant validation logic 
         ValidateIssuer = false, 
        }, 
        Notifications = new OpenIdConnectAuthenticationNotifications() 
        { 
         SecurityTokenValidated = (context) => 
         { 
          return Task.FromResult(0); 
         }, 
         AuthorizationCodeReceived = (context) => 
         { 
          var code = context.Code; 

          ClientCredential credential = new ClientCredential(clientId, appKey); 
          string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; 
          string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value; 

          AuthenticationContext authContext = new AuthenticationContext(aadInstance + tenantID, new ADALTokenCache(signedInUserID)); 
          AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
           code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceID); 

          return Task.FromResult(0); 
         }, 
         AuthenticationFailed = (context) => 
         { 
          context.OwinContext.Response.Redirect("/Home/Error"); 
          context.HandleResponse(); // Suppress the exception 
          return Task.FromResult(0); 
         } 
        } 
       }); 

     } 
    } 

这里是获取用户的基本信息

 private ApplicationDbContext db = new ApplicationDbContext(); 
     private string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; 
     private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"]; 
     private string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"]; 
     private string graphResourceID = "https://graph.windows.net"; 

     // GET: UserProfile 
     public async Task<ActionResult> Index() 
     { 
      string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; 
      string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 
      try 
      { 
       Uri servicePointUri = new Uri(graphResourceID); 
       Uri serviceRoot = new Uri(servicePointUri, tenantID); 
       ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(serviceRoot, 
         async() => await GetTokenForApplication()); 

       // use the token for querying the graph to get the user details 

       var result = await activeDirectoryClient.Users 
        .Where(u => u.ObjectId.Equals(userObjectID)) 
        .ExecuteAsync(); 
       IUser user = result.CurrentPage.ToList().First(); 

       return View(user); 
      } 
      catch (AdalException) 
      { 
       // Return to error page. 
       return View("Error"); 
      } 
      // if the above failed, the user needs to explicitly re-authenticate for the app to obtain the required token 
      catch (Exception) 
      { 
       return View("Relogin"); 
      } 
     } 

     public void RefreshSession() 
     { 
      HttpContext.GetOwinContext().Authentication.Challenge(
       new AuthenticationProperties { RedirectUri = "/UserProfile" }, 
       OpenIdConnectAuthenticationDefaults.AuthenticationType); 
     } 

     public async Task<string> GetTokenForApplication() 
     { 
      string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value; 
      string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; 
      string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 

      // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc) 
      ClientCredential clientcred = new ClientCredential(clientId, appKey); 
      // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database 
      AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID, new ADALTokenCache(signedInUserID)); 
      AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenSilentAsync(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId)); 
      return authenticationResult.AccessToken; 
     } 

我也试过this和获取错误代码

Insufficient privileges to complete the operation. 

我的应用程序具有下列权限

  • 登录和读取用户配置文件
  • 读取目录数据

代码获取用户的照片

var servicePoint = new Uri("https://graph.windows.net"); 
var serviceRoot = new Uri(servicePoint, "<your tenant>"); //e.g. xxx.onmicrosoft.com 
const string clientId = "<clientId>"; 
const string secretKey = "<secretKey>";// ClientID and SecretKey are defined when you register application with Azure AD 
var authContext = new AuthenticationContext("https://login.windows.net/<tenant>/oauth2/token"); 
var credential = new ClientCredential(clientId, secretKey); 
ActiveDirectoryClient directoryClient = new ActiveDirectoryClient(serviceRoot, async() => 
{ 
    var result = await authContext.AcquireTokenAsync("https://graph.windows.net/", credential); 
    return result.AccessToken; 
}); 

var user = await directoryClient.Users.Where(x => x.UserPrincipalName == "<username>").ExecuteSingleAsync(); 
DataServiceStreamResponse photo = await user.ThumbnailPhoto.DownloadAsync(); 
using (MemoryStream s = new MemoryStream()) 
{ 
    photo.Stream.CopyTo(s); 
    var encodedImage = Convert.ToBase64String(s.ToArray()); 
} 
+0

你解决了这个问题吗,你需要进一步的帮助吗? –

+0

@Bruce - MSFT请在你的回答下看看我的评论。 – user3881465

回答

0

据我所知,在读取目录数据许可将允许你的应用程序读取所有(例如用户,群组和应用程序等)。我假设可以利用jwt.io来解码您的access_token并检查scp并确保范围Directory.Read.All(读取目录数据)和User.Read(启用登录和读取用户配置文件)存在如下:

enter image description here

注:的权限读取目录数据是一个代理权限,必须由管理员同意。

enter image description here

您授予的权限之后,你可以等待一段时间,并与您的应用程序检查:如果您是AAD的管理员,您可以通过点击授予权限在下面的截图所示按钮授予权限并确保Directory.Read.All范围已被添加到您的解码access_token

enter image description here

UPDATE:

基于您的代码,您正在使用的客户端凭证流的令牌获取,在这一点上,你需要设置应用程序的权限Windows Azure中的Active Directory API如下:

enter image description here

等待一段时间,解码你的access_token和检查roles下授予的权限如下:

enter image description here

UPDATE2:

正如你说,你是不是微软目录下的管理,我对自己的AAD进行了测试,我可以授予权限,并且可以在我身边运行。此外,我注意到您正在使用代码流并检索委派的权限以成功获取用户的基本信息。您正在使用客户端凭据流获取用户的基本信息,但您没有授予权限的权限。我假设您可以利用ADALTokenCache并使用GetTokenForApplication来检索access_token,然后获取用户照片。

+0

对不起,延迟回复。我在jwt.io中检查了访问令牌,发现没有像'scp'这样的条目。 – user3881465

+0

我已经做了相同的委托权限,并得到管理员的同意。 – user3881465

+0

我已经更新了我的问题,现在您可以看到我用于获取用户照片及其访问令牌的代码。 – user3881465

相关问题