2016-11-15 3 views
1

J'ai réussi à configurer une application multi-locataire. Pour l'instant, je suis capable d'authentifier l'utilisateur et d'utiliser des jetons pour accéder à d'autres ressources. (Microsoft Graph & Microsoft AD graphique)Accès B2B dans une application multi-locataires

Maintenant, je veux travailler B2B. flux de courant: - signes utilisateur dans - AuthorizationCodeReceived obtient les acquiert le jeton (via point final $ commonAuthority) - Lorsque vous demandez un jeton pour le graphique Ad, j'utilise le tenantAuthority de $

Cela fonctionne parfaitement quand $ tenantAuthority Toutefois, si je me connecte avec un autre utilisateur (d'un autre locataire, en accordant la confiance au locataire actuel) et que j'utilise $ tenantAuthority = autorité de confiance, alors je suis toujours le même que celui où le compte a été créé.

l'erreur suivante: Echec du jeton d'actualisation: AADSTS65001: L'utilisateur ou l'administrateur n'a pas de compte Pour utiliser l'application avec l'ID

Si je remplace $

Toute aide serait grandement appréciée.

Mise à jour: Code échantillon

App a deux locataires (tenantA en tenantB) et je vais utiliser un utilisateur de tenantB avec tenantA donné une fiducie à cet utilisateur.

AuthorizationCodeReceived = async context => 
        { 
         TenantContext.TenantId = "someguid"; 
         var tenantId = 
          TenantContext.TenantId; 

         // get token cache via func, because the userid is only known at runtime 
         var getTokenCache = container.Resolve<Func<string, TokenCache>>(); 
         var userId = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.ObjectIdentifier).Value; 
         var tokenCache = getTokenCache(userId); 
         var authenticationContext = new AuthenticationContext($"{configuration.Authority}", 
          tokenCache); 

         await authenticationContext.AcquireTokenByAuthorizationCodeAsync(
          context.Code, 
          new Uri(context.Request.Uri.GetLeftPart(UriPartial.Authority)), 
          new ClientCredential(configuration.ClientId, configuration.ClientSecret), 
          configuration.GraphResourceId); 
        } 

Ce code fonctionne parfaitement. Se connecter avec un utilisateur des deux locataires fonctionne parfaitement. Mais quand j'ai besoin du Client de service graphique ou de ActiveDirectoryClient, j'ai besoin d'obtenir des jetons d'accès pour pouvoir adresser une API à un certain locataire. Je récupère les jetons d'accès comme celui-ci:

public IGraphServiceClient CreateGraphServiceClient() 
    { 
     var client = new GraphServiceClient(
      new DelegateAuthenticationProvider(
       async requestMessage => 
       { 
        Logger.Debug("Retrieving authentication token to use in Microsoft Graph."); 

        string token; 
        var currentUserHomeTenantId = TenantContext.TenantId; 
        var currentUserObjectId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.ObjectIdentifier).Value; 
        var authenticationContext = 
         new AuthenticationContext($"{_configuration.TenantAuthorityPrefix}{currentUserHomeTenantId}", 
          _tokenCacheFactoryMethod(currentUserObjectId)); 
        var clientCredential = new ClientCredential(_configuration.ClientId, _configuration.ClientSecret); 

        try 
        { 
         token = await GetTokenSilently(authenticationContext, _configuration.GraphResourceId, currentUserObjectId); 
        } 
        catch (AdalSilentTokenAcquisitionException e) 
        { 
         Logger.Error("Failed to retrieve authentication token silently, trying to refresh the token.", e); 
         var result = await authenticationContext.AcquireTokenAsync(_configuration.GraphResourceId, clientCredential); 
         token = result.AccessToken; 
        } 

        requestMessage.Headers.Authorization = new AuthenticationHeaderValue(AuthenticationHeaderKeys.Bearer, token); 
       })); 

     return client; 
    } 


    public IActiveDirectoryClient CreateAdClient() 
    { 
     var currentUserHomeTenantId = TenantContext.TenantId; 
     var currentUserObjectId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.ObjectIdentifier).Value; 
     var graphServiceUrl = $"{_configuration.AdGraphResourceId}/{currentUserHomeTenantId}"; 
     var tokenCache = _tokenCacheFactoryMethod(currentUserObjectId); 

     var client = new ActiveDirectoryClient(new Uri(graphServiceUrl), 
      () => GetTokenSilently(
       new AuthenticationContext(
        $"{_configuration.TenantAuthorityPrefix}{ClaimsPrincipal.Current.FindFirst(ClaimTypes.TenantId).Value}", tokenCache 
       ), 
       _configuration.AdGraphResourceId, currentUserObjectId 
      )); 

     return client; 
    } 

Quand je fais une demande avec l'un des deux SDK client de, j'obtenu l'erreur suivante: Failed le jeton de rafraîchissement: AADSTS65001: L'utilisateur ou l'administrateur n'a pas consenti à Utilisez l'application avec ID.

+0

Avez-vous vu la page de consentement lors de votre connexion en utilisant les comptes d'un autre locataire? Si non, cela vous dérangerait-il de partager le morceau de code et de vous connecter? –

Répondre

0

Modification de la méthode de capture lors de la récupération du jeton a fait l'affaire:

if(e.ErrorCode == "failed_to_acquire_token_silently") 
{ 
    HttpContext.Current.Response.Redirect(authenticationContext.GetAuthorizationRequestUrlAsync(resourceId, _configuration.ClientId, new Uri(currentUrl), 
         new UserIdentifier(currentUserId, UserIdentifierType.UniqueId), string.Empty); 
} 
0

Je ne vois pas que vous le mentionnez ainsi: dans une collaboration B2B, vous devez d'abord inviter l'utilisateur d'un autre locataire. Les étapes sont comme ça:

  • invitent et autoriser un ensemble d'utilisateurs externes en téléchargeant une des valeurs séparées par des virgules - fichier CSV
  • Invitation sera envoyée aux utilisateurs externes.
  • L'utilisateur invité se connectera à un compte professionnel existant auprès de Microsoft (géré dans Azure AD) ou obtiendra un nouveau compte professionnel dans Azure AD.
  • Après connecté, l'utilisateur sera redirigé vers l'application qui a été partagé avec eux

Cela fonctionne parfaitement dans mon cas.

En ce qui concerne certains problèmes que j'ai Detect:

Trailing «/» à la fin de la ressource Active Directory - essayer de l'enlever car cela pourrait causer des problèmes. Bellow vous trouverez un code pour obtenir les en-têtes d'authentification:

string aadTenant = WebServiceClientConfiguration.Settings.ActiveDirectoryTenant; 
string clientAppId = WebServiceClientConfiguration.Settings.ClientAppId; 
string clientKey = WebServiceClientConfiguration.Settings.ClientKey; 
string aadResource = WebServiceClientConfiguration.Settings.ActiveDirectoryResource; 

AuthenticationContext authenticationContext = new AuthenticationContext(aadTenant); 
ClientCredential clientCredential = new ClientCredential(clientAppId, clientKey); 
UserPasswordCredential upc = new UserPasswordCredential(WebServiceClientConfiguration.Settings.UserName, WebServiceClientConfiguration.Settings.Password); 

AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(aadResource, clientAppId, upc); 

return authenticationResult.CreateAuthorizationHeader(); 

Applications provisionnés dans AD Azure ne sont pas autorisés à utiliser la subvention implicite OAuth2 par défaut. Vous devez opter explicitement dans - plus de détails peuvent être trouvés ici: Azure AD OAuth2 implicit grant

+0

Juste une pensée, je ne peux pas invoquer cette opération d'ajout et invitant en utilisant l'API graphique. – Rahul

+0

Je ne pense pas mais je ne suis pas sûr à 100% ... –

+0

Ajouter et inviter un utilisateur sont des choses séparées. Cela invite un utilisateur et il est toujours en aperçu. https://graph.microsoft.io/en-us/docs/api-reference/beta/resources/invitation - Rest API – Rahul