2016-06-24 10 views
6

Wir schreiben einen WCF-Dienst, der in Dynamics CRM 2016 Online integriert werden muss. Ich versuche, mithilfe von ADAL mit der Methode AcquireTokenAsync() zu authentifizieren. Das Problem besteht darin, dass ein Popup-Fenster angezeigt wird, in dem der Benutzer nach Anmeldeinformationen gefragt wird. Natürlich ist unsere Anwendung eine Dienstleistung, das ist nicht was wir wollen. Wir haben nach einer Möglichkeit zur Authentifizierung gesucht, ohne diese Popup-Box zu haben.C# ADAL AcquireTokenAsync() ohne Popup-Feld

Es gibt eine Klasse namens AuthenticationContextIntegratedAuthExtensions, die mit "Benutzername/Passwortfluss" helfen soll. Es hat die einzige Methode AcquireTokenAsync, die die Popup-Box unterdrückt, aber wir haben keine Möglichkeit gefunden, das Passwort an sie zu übergeben. Wenn nur der Benutzername ausgeführt wird, wird die Ausnahme ausgelöst, die im Wesentlichen besagt, dass "kein Kennwort angegeben wurde".

Hat jemand eine Idee, wie man das umgeht? Muss nicht einmal ADAL sein. Nur etwas, um das OAuth-Token zu erhalten.

Antwort

4
private static string API_BASE_URL = "https://<CRM DOMAIN>.com/"; 
private static string API_URL = "https://<CRM DOMAIN>.com/api/data/v8.1/"; 
private static string CLIENT_ID = "<CLIENT ID>"; 

static void Main(string[] args) 
{ 
    var ap = AuthenticationParameters.CreateFromResourceUrlAsync(
       new Uri(API_URL)).Result; 

    var authContext = new AuthenticationContext(ap.Authority, false); 

    var userCredential = new UserCredential("<USERNAME>", "<PASSWORD>"); 

    var result = authContext.AcquireToken(API_BASE_URL, CLIENT_ID, userCredential); 

    var httpClient = HttpWebRequest.CreateHttp(Path.Combine(API_URL, "accounts")); 
    httpClient.Headers.Add(HttpRequestHeader.Authorization, "Bearer:" + result.AccessToken); 
    using (var sr = new StreamReader(httpClient.GetResponse().GetResponseStream())) 
    { 
     Console.WriteLine(sr.ReadToEnd()); 
    } 
} 

Hinweis: Ich bin eine ältere Version von ADAL mit (2.19.208020213), wie es dem Parameter Passwort erscheint ist aus dem UserCredential Konstruktor genommen worden.

EDIT: Die neuesten Versionen von ADAL UserPasswordCredential haben, die anstelle von UserCredential verwendet werden können (und wahrscheinlich so schnell hinzugefügt, wie Password von UserCredential entfernt wurde)

EDIT 2: CRM unterstützt jetzt Server to Server Authentication die ermöglicht es Ihnen, einen Anwendungsbenutzer zu erstellen.

+0

Ja. Das Passwortfeld wurde aus welchem ​​Grund auch immer entfernt. Tatsächlich haben wir keine Klasse oder Methode gefunden, die etwas mit Passwörtern zu tun hat. Einige Klassen haben einen Konstruktor, der den Benutzernamen UserIdentifier akzeptiert. Der Zweck scheint jedoch eher die automatische Vervollständigung als der Versuch einer stillen Authentifizierung zu sein. – eltaro

+0

Richtig, ich bin mir nicht sicher, warum es auch entfernt wurde (dieser Blog http://www.cloudidentity.com/blog/2014/07/08/using-adal-net-to-authentica-user-vy-usernamespassword/ ist das, an das ich mich erinnere, als ich es zum ersten Mal gelesen habe. Aber wenn Sie die oben genannte spezifische Version verwenden, können Sie sich ohne ein Popup authentifizieren und das Token funktioniert für Anfragen gegen CRM. –

+0

Scheint so, als müssten wir Ihre Lösung verwenden. Die eine, die ich hier gepostet habe, lässt uns nicht auf das CRM zugreifen und gibt 401 Fehler. – eltaro

0

Okay, endete damit eine Lösung zu finden.

Sofern Sie Ihre Anwendung bei Azure AD registriert haben (als Web App/Web API, keine native Anwendung), erhalten Sie eine Client-ID und einen geheimen Schlüssel für diese Anwendung.

Der Code des Tokens zu erwerben, ohne ein Pop-up-Fenster ist wie folgt:

AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(
         new Uri(resource+"/api/data/v8.1")).Result; 

AuthenticationContext ac = new AuthenticationContext(ap.Authority); 

AuthenticationResult r = await ac.AcquireTokenAsync(ap.Resource, new ClientCredential(clientId,clientSecret)); 

Ressource die Basis-URL Ihrer Dynamics CRM-Bereitstellung ist.

Authentifizierungsparameter werden zur Laufzeit wie in dieser MSDN acticle vorgeschlagen erkannt.

+0

Haben Sie versucht, dieses Token mit einem Aufruf gegen CRM WebAPI zu machen? Ich wäre gespannt, ob das Token, das Sie haben, funktioniert, wenn es an CRM weitergegeben wird, da kein Benutzer angegeben wurde. Wenn es funktioniert, wer sind die Anrufe, die wie in CRM gemacht werden? –

+1

Noch nicht. Wenn Sie die Anwendung jedoch in Azure AD registrieren, können Sie ihr die Berechtigung für Dynamics CRM erteilen. Es gibt kein spezielles CRM, wohlgemerkt, ich nehme an, Sie erhalten Zugriff auf alle Instanzen, die auf diesem Azure AD bereitgestellt werden. Und die AuthenticationParameters werden durch Pingen unserer CRM-Instanz erworben, die wir dann zur Authentifizierung gegenüber dem zugrunde liegenden AD verwenden, indem wir AuthenticationParameters.Resource an AcquireTokenAsync() übergeben. – eltaro

+0

Aber Sie sind nicht als Benutzer authentifiziert, CRM ermöglicht "delegierte Berechtigungen" und nicht "Anwendungsberechtigungen" bedeutet, dass Sie einen angemeldeten Benutzer benötigen. Wenn Sie dieses Token an CRM übergeben, erhalten Sie wahrscheinlich eine 401. –

2

Für was es wert ist, ohne ADAL mit

var postData = new List<KeyValuePair<string, string>> 
     { 
      new KeyValuePair<string, string>("resource", cred.ResourceId), 
      new KeyValuePair<string, string>("grant_type", "client_credentials"), 
      new KeyValuePair<string, string>("client_id", cred.ClientId), 
      new KeyValuePair<string, string>("client_secret", cred.ClientSecret), 

     }; 

     using (var client = new HttpClient()) { 

      string baseUrl = "https://login.windows.net/YourAADInstanceName.onmicrosoft.com/oauth2/"; 
      client.BaseAddress = new Uri(baseUrl);     
      client.DefaultRequestHeaders.Accept.Clear(); 
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

      var content = new FormUrlEncodedContent(postData); 

      HttpResponseMessage response = await client.PostAsync("token", content);    
      string jsonString = await response.Content.ReadAsStringAsync();     
      var responseData = JsonConvert.DeserializeObject<Token>(jsonString); 
      return responseData; 
     } 
+0

Dies authentifiziert und gibt ein accessToken zurück, aber wenn ich dieses Token verwende, gibt es eine 401. – Justin

Verwandte Themen