5

Ich habe eine in Azure AD registrierte Konsolenanwendung, die eine Verbindung zu CRM Online herstellt (konfiguriert mit these steps). Es fragt die Web-API ab.ADAL-Authentifizierung ohne Dialogfeldaufforderung

Die Anwendung muss ohne Benutzerinteraktion ausgeführt werden ... aber leider schlägt der Aufruf an AcquireTokenSilentAsync immer fehl und nur AcquireTokenAsync funktioniert. Dadurch wird ein Benutzeranmeldedialog angezeigt, der die Benutzerinteraktionsanforderung nicht erfüllt!

Gibt es einen Weg zu verhindern diese Aufforderung, entweder durch Speichern der Anmeldung irgendwo auf dem Client-Rechner (was bisher nicht funktioniert hat) oder vielleicht mit einem Zertifikat (aber wie machst du das?) Oder etwas sonst?

Ich verwende die ADAL für .NET v3.10.305110106 Version. Der folgende Code wird verwendet, um die Authentifizierung:

private static async Task PerformOnlineAuthentication() 
{ 
    _authInfo = new AuthInfo(); // This is just a simple class of parameters 

    Console.Write("URL (include /api/data/v8.x): "); 
    var url = Console.ReadLine(); 

    BaseUri = new Uri(url); 
    var absoluteUri = BaseUri.AbsoluteUri; 
    _authInfo.Resource = absoluteUri; 

    Console.Write("ClientId: "); 
    var clientId = Console.ReadLine(); 
    _authInfo.ClientId = clientId; 

    Console.Write("RedirectUri: "); 
    var redirectUri = Console.ReadLine(); 
    _authInfo.RedirectUri = new Uri(redirectUri); 

    var authResourceUrl = new Uri($"{_authInfo.Resource}/api/data/"); 
    var authenticationParameters = await AuthenticationParameters.CreateFromResourceUrlAsync(authResourceUrl); 

    _authInfo.AuthorityUrl = authenticationParameters.Authority; 
    _authInfo.Resource = authenticationParameters.Resource; 

    _authInfo.Context = new AuthenticationContext(_authInfo.AuthorityUrl, false); 
} 

private static async Task RefreshAccessToken() 
{ 
    if (!IsCrmOnline()) 
     return; 

    Console.WriteLine($"Acquiring token from: {_authInfo.Resource}"); 
    AuthenticationResult authResult; 
    try 
    { 
     authResult = await _authInfo.Context.AcquireTokenSilentAsync(_authInfo.Resource, _authInfo.ClientId); 
    } 
    catch (AdalSilentTokenAcquisitionException astae) 
    { 
     Console.WriteLine(astae.Message); 
     authResult = await _authInfo.Context.AcquireTokenAsync(_authInfo.Resource, _authInfo.ClientId, _authInfo.RedirectUri, new PlatformParameters(PromptBehavior.RefreshSession)); 
    } 

    HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken); 
} 
+0

hallo, hast du dieses überprüfen https://github.com/Azure-Samples/active-directory-dotnet-native-headless? es hat einmal Benutzername - pwd nur eingeben. – Aravind

Antwort

5

Dank @aravind, die die active-directory-dotnet-native-headless Probe hingewiesen.

Das Beispiel enthält eine FileCache class, die von Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache erbt. Diese Klasse verwaltet das Zwischenspeichern der Anmeldeinformationen in eine verschlüsselte Datei auf der Festplatte. Dies bedeutet, dass beim ersten Start nur eine Eingabeaufforderung angezeigt wird und anschließend die Anmeldedaten lokal gespeichert werden.

Die letzten Teile des Puzzles sind:

  1. eine andere Konstruktor Unterschrift aufrufe AuthenticationContext mit dem Filecache zu initialisieren:

    _authInfo.Context = new AuthenticationContext(
        _authInfo.AuthorityUrl, false, new FileCache()); 
    
  2. Beziehen Anmeldeinformationen vom Benutzer in ein Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential Objekt (siehe die TextualPrompt()method in the sample)

  3. Übergeben Sie die Anmeldeinformationen an eine andere Methode Signatur für AcquireTokenAsync():

    authResult = await _authInfo.Context.AcquireTokenAsync(
        _authInfo.Resource, _authInfo.ClientId, userCredential); 
    
0

Wenn „Anwendung muss ohne Benutzereingriff laufen“ ClientCredential Verwendung fließen zB:

public static string GetAccessTokenUsingClientCredentialFlow(Credential cred) {   

     AuthenticationContext ac = new AuthenticationContext(cred.Authority); 
     AuthenticationResult r = ac.AcquireTokenAsync(cred.ResourceId, new ClientCredential(cred.ClientId, cred.ClientSecret)).Result; 
     return r.AccessToken; 
    }