2017-07-15 3 views
2

J'ai une application multi-locataires en azur. Je suis capable de me connecter et obtenir des informations de base de chanté dans l'utilisateur comme nom et email.Obtenez l'image du profil de l'utilisateur à partir de Azure

Maintenant, j'ai besoin d'obtenir l'image de profil de l'utilisateur d'azur. J'ai essayé quelques solutions fournies sur internet mais aucune d'entre elles ne fonctionne pour moi.

Voici mon Startup.Auth.cs Code

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); 
         } 
        } 
       }); 

     } 
    } 

Voici le code pour obtenir des informations de base de l'utilisateur

 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; 
     } 

J'ai aussi essayé this et obtenir erreur

Insufficient privileges to complete the operation. 

Mon application dispose des autorisations suivantes

  • Connectez-vous et lire le profil de l'utilisateur
  • données d'annuaire Lire

code pour obtenir user photo

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

Avez-vous résolu ce problème, avez-vous besoin d'aide? –

+0

@Bruce - MSFT s'il vous plaît me voir les commentaires sous votre réponse. – user3881465

Répondre

0

AFAIK, les données répertoire en lecture autorisation permettrait à votre application de lire toutes des données dans le répertoire de l'organisation, tels que les utilisateurs, groupes et applications, etc. Je suppose que pourrait tirer parti jwt.io pour décoder votre access_token et vérifier le scp et assurez-vous que la portée Directory.Read.All (Lire les données de l'annuaire) et User.Read (activer la connexion et lire le profil de l'utilisateur) existent comme suit:

enter image description here

Note: L'autorisation Lire les données d'annuaire est une autorisation de délégation et doit être consenti par l'administrateur. Si vous êtes administrateur de votre DAA, vous pouvez accorder l'autorisation en cliquant sur autorisations de subvention bouton indiqué sur la capture d'écran suivante:

enter image description here

Après avoir obtenu la permission, vous pourriez attendre pendant un certain temps et vérifier avec votre application et assurez-vous que la portée Directory.Read.All a été ajoutée à votre access_token décodé.

enter image description here

MISE À JOUR:

En fonction de votre code, vous utilisez le flux d'informations d'identification client pour l'acquisition de jetons, à ce stade, vous devez définir APPLICATION AUTORISATIONS pour Windows Azure Active Directory API comme suit:

enter image description here

Attendez un moment et décode votre access_token et vérifiez les autorisations accordées en vertu roles comme suit:

enter image description here

MAJ2:

Comme vous avez dit que vous n'êtes pas l'administrateur sous le répertoire Microsoft, J'ai testé cela sur mon propre DAA, je pouvais accorder des permissions et ça pouvait marcher de mon côté. De plus, j'ai remarqué que vous utilisez le flux de code et récupérez les permissions déléguées pour obtenir les informations de base de l'utilisateur avec succès. Vous utilisez le flux d'informations d'identification client pour obtenir les informations de base de l'utilisateur, mais vous n'êtes pas autorisé à accorder des autorisations. J'ai supposé que vous pourriez tirer parti ADALTokenCache et utiliser GetTokenForApplication pour récupérer le access_token, puis obtenir la photo de l'utilisateur.

+0

Désolé pour la réponse tardive. J'ai vérifié le jeton d'accès dans jwt.io et trouvé qu'il n'y a pas une telle entrée comme 'scp'. – user3881465

+0

J'ai déjà fait les mêmes autorisations de délégation et j'ai consenti par l'administrateur. – user3881465

+0

J'ai mis à jour mes questions maintenant vous pouvez voir le code que j'utilise pour obtenir la photo de l'utilisateur et son jeton d'accès. – user3881465