Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# ADAL AcquireTokenAsync() without pop-up box

We are writing a WCF service which has to integrate with Dynamics CRM 2016 Online. I'm trying to authenticate using ADAL, using method AcquireTokenAsync(). Problem is, it displays a pop-up box, prompting the user for credentials. Naturally, our application being a service, this isn't what we want. We've been searching for a way to authenticate without having this pop-up box.

There is a class called AuthenticationContextIntegratedAuthExtensions, which is supposed to assist with "username/password flow". It has the single method AcquireTokenAsync, which suppresses the pop-up box, but we haven't found any way to pass the password to it. When run with just the username, it raises the exception that basically says "no password was supplied".

Does anyone have any idea how to work around this? Doesn't even have to be ADAL. Just something to acquire the OAuth token.

like image 724
eltaro Avatar asked Jun 24 '16 09:06

eltaro


2 Answers

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

Note: I'm using an older version of ADAL (2.19.208020213) as it appears the password parameter has been taken out of the UserCredential constructor.

EDIT: Latest versions of ADAL have UserPasswordCredential which can be used in place of UserCredential (and probably was added as soon as Password was removed from UserCredential)

EDIT 2: CRM now supports Server to Server Authentication which allows you to create an application user.

like image 111
Matt Dearing Avatar answered Sep 20 '22 18:09

Matt Dearing


For what it's worth without using ADAL

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;
        }
like image 44
mothswiller Avatar answered Sep 23 '22 18:09

mothswiller