2016-11-03 8 views
1

Ich richte eine Anwendung mit mehreren Mandanten ein und habe Probleme beim Erstellen eines GraphServiceClient.Vom Authentifizierungskontext empfangener Token funktioniert nicht

Ich muss folgende AuthorizationCodeReceived:

AuthorizationCodeReceived = async context => 
        { 
         var tenantId = 
          context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; 

         var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/"+ tenantId); 
         await authenticationContext.AcquireTokenByAuthorizationCodeAsync(
          context.Code, 
          new Uri("http://localhost:21925"), 
          new ClientCredential(ClientId, ClientSecret), 
          "https://graph.microsoft.com"); 
        } 

Dies funktioniert perfekt den Benutzer zu authentifizieren. Ich bin mit Fiedler, und ich sehe, dass eine neue Träger-Token von login.microsoftonline.com/{tenantid}/oauth2/token

gegeben wurden, als ein neues Graph-Service-Client Erstellen ich die folgenden Factory-Methode verwenden:

public IGraphServiceClient CreateGraphServiceClient() 
    { 
     var client = new GraphServiceClient(
      new DelegateAuthenticationProvider(
       async requestMessage => 
       { 
        string token; 
        var currentUserId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 
        var currentUserHomeTenantId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; 
        var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/" + currentUserHomeTenantId + "/"); 
        var clientCredential = new ClientCredential(_configuration.ClientId, _configuration.ClientSecret); 

        try 
        { 
         var authenticationResult = await authenticationContext.AcquireTokenSilentAsync(
          GraphResourceId, 
          clientCredential, 
          new UserIdentifier(currentUserId, UserIdentifierType.UniqueId)); 

         token = authenticationResult.AccessToken; 
        } 
        catch (AdalSilentTokenAcquisitionException e) 
        { 
         var result = await authenticationContext.AcquireTokenAsync(GraphResourceId, clientCredential); 
          token = result.AccessToken; 
        } 

        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token); 
       })); 

     return client; 
    } 

Diese Methode löst immer eine AdalSilentAcquisitionException aus, und AcquireTokenAsync ruft ein neues Token ab.

Mit diesem Token kann ich "Ich" nicht in der Grafik anfordern. Ich bekomme die folgende Ausnahme: message = Ressource 'einige GUID' ist nicht vorhanden oder eines seiner abgefragten Referenz-Eigenschaft Objekte sind nicht vorhanden.

Allerdings, wenn ich debuggen bin und ich das Token ändern, bevor es an die Kopfzeile übergeben wird, mit dem Wert von dem, den ich zuvor direkt nach dem Login erhalten habe (erhalten von login.microsoftonline.com/{tenantid}/oauth2/token), dann funktioniert der API-Aufruf.

Weiß jemand, was ich falsch mache? Er kann ich das acquirectedenstillyly arbeiten lassen?

Aktualisieren: Ich habe die Codebeispiele aktualisiert. Ich habe den benutzerdefinierten Cache entfernt und jetzt scheint alles zu funktionieren.

Wie kann ich einen benutzerdefinierten Cache basierend auf den http-Sitzungen erstellen, um sicherzustellen, dass AcquireTokenSilently funktioniert.

Vorschau von nicht-Token-Cache arbeiten:

public class WebTokenCache : TokenCache 
{ 
    private readonly HttpContext _httpContext; 
    private readonly string _cacheKey; 
    public WebTokenCache() 
    { 
     _httpContext = HttpContext.Current; 
     var claimsPrincipal = (ClaimsPrincipal) HttpContext.Current.User; 
     _cacheKey = BuildCacheKey(claimsPrincipal); 

     AfterAccess = AfterAccessNotification; 

     LoadFromCache(); 
    } 

    private string BuildCacheKey(ClaimsPrincipal claimsPrincipal) 
    { 
     var clientId = claimsPrincipal.FindFirst("aud").Value; 
     return $"{claimsPrincipal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value}_TokenCache"; 
    } 

    private void LoadFromCache() 
    { 
     var token = _httpContext.Cache[_cacheKey]; 
     if (token == null) return; 

     Deserialize((byte[]) token); 
    } 

    private void AfterAccessNotification(TokenCacheNotificationArgs args) 
    { 
     if (!HasStateChanged) return; 

     if (Count > 0) 
     { 
      _httpContext.Cache[_cacheKey] = Serialize(); 
     } 
     else 
     { 
      _httpContext.Cache.Remove(_cacheKey); 
     } 

     HasStateChanged = false; 
    } 
} 

Antwort

1

Ich versuche, den Code oben verwenden und es funktioniert mich gut bilden.

Bitte stellen Sie sicher, dass die GraphResourceId ist https://graph.microsoft.com (Diese Ressource ersten Mal in Ihrem startUp Klasse angefordert wird), da die Methode AcquireTokenSilentAsync werden versuchen, das Token aus dem Cache auf der Grundlage der resrouce abzurufen.

+0

Fei Wue, danke für Ihre Antwort, siehe meine aktualisierte Frage. Für jetzt habe ich den benutzerdefinierten Token-Cache entfernt und alles scheint zu funktionieren. Hast du eine Idee, wie ich einen benutzerdefinierten TokenCache verwenden kann? (Da es nicht empfohlen wird, TokenCache in Produktions-Webanwendungen zu verwenden) – Identity

+0

Damit der benutzerdefinierte Cache funktioniert, müssen Sie ihn jedes Mal verwenden, wenn Sie den Authentifizierungskontext erstellen. In diesem Szenario müssen Sie den Cache auch in der Startklasse verwenden, wenn Sie das Token mithilfe von OAuth-Code erwerben. –

+0

Das hat den Trick für mich getan. Danke für deine Antwort. Noch eine Frage, mache ich das Richtige, wenn eine AdalSilentTokenAcquisitionException ausgelöst wird? Denn wenn das Token über AcquireTokenAsync abgerufen wird, scheint das Token immer nicht gültig zu sein. Haben Sie irgendwelche Ideen? – Identity

Verwandte Themen