Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AuthenticationContext.AcquireTokenAsync

Tags:

c#

azure

I would like to be programmatically able to get a token from Azure.

I call GetAToken().Wait(); and it fails.

and the method is:

public async Task<string> GetAToken()
{
    // authentication parameters
    string clientID = "*********";
    string username = "<azure login>";
    string password = "<azure login password>";
    string directoryName = "<AD Domain name>";

    ClientCredential cc = new ClientCredential(clientID, password);
    var authenticationContext = new AuthenticationContext(
           "https://login.windows.net/" + directoryName);

    AuthenticationResult result = await authenticationContext.AcquireTokenAsync(
           "https://management.core.windows.net/", cc);

    if (result == null)
    {
        throw new InvalidOperationException("Failed to obtain the JWT token");
    }

    string token = result.AccessToken;

    return token;
}
like image 578
stephen robinson Avatar asked Jan 18 '17 22:01

stephen robinson


People also ask

What is AuthenticationContext?

AuthenticationContext(String, Boolean, TokenCache) Constructor to create the context with the address of the authority and flag to turn address validation off. Using this constructor, address validation can be turned off. Make sure you are aware of the security implication of not validating the address.


2 Answers

So not sure if you are doing this on Android, iOS or Xamarin.Forms. Below is how I will authenticate with ADAL and Azure (the code is working on my end):

On Android:

public async Task<AuthenticationResult> Authenticate(Activity context, string authority, string resource, string clientId, string returnUri)
{
    var authContext = new AuthenticationContext(authority);
    if (authContext.TokenCache.ReadItems().Any())
        authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);

    var uri = new Uri(returnUri);
    var platformParams = new PlatformParameters(context);
    try
    {
        var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
        return authResult;
    }
    catch (AdalException e)
    {
        return null;
    }
}

On iOS:

public async Task<AuthenticationResult> Authenticate(UIViewController controller, string authority, string resource, string clientId, string returnUri)
    {
        var authContext = new AuthenticationContext(authority);
        if (authContext.TokenCache.ReadItems().Any())
            authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);

        var controller = UIApplication.SharedApplication.KeyWindow.RootViewController;
        var uri = new Uri(returnUri);
        var platformParams = new PlatformParameters(controller);

        try
        {
            var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
            return authResult;
        }
        catch (AdalException e)
        {
            return null;
        }
    }

On UWP:

public async Task<AuthenticationResult> Authenticate(string authority, string resource, string clientId, string returnUri)
{
    var authContext = new AuthenticationContext(authority);
    if (authContext.TokenCache.ReadItems().Any())
        authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);

    var uri = new Uri(returnUri);
    var platformParams = new PlatformParameters(PromptBehavior.Auto);
    try
    {
        var authResult = await authContext.AcquireTokenAsync(resource, clientId, uri, platformParams);
        return authResult;
    }
    catch (AdalException e)
    {
        return null;
    }
}

Variable that I pass into the methods above:

string authority = "https://login.windows.net/common";
string ResourceID = "Backend ClientId";//Backend (web app)
string clientId = "Native App ClientId";//native app
string returnUri = "https://{My Azure Site}.azurewebsites.net/.auth/login/done";

If you want to do this in Xamarin.Forms, below are links to my GitHub solution where I have exposed these methods through the DependencyService.

  • PCL implementation
  • iOS implementation
  • Android Implementation

I hope this helps! If you get any errors from your response, check to make sure you have your permissions setup in Azure correctly. I do it like this. Another great resource is Adrian Hall's Xamarin/Azure book

EDIT: Added UWP stuff

like image 96
BrewMate Avatar answered Sep 29 '22 09:09

BrewMate


If what you are trying to do is call the Azure APIs as you, there are a few things you should do differently.

  1. Create an app in Azure AD that has permissions to access the Azure API
    1. If you want to call Service Management API, then add that as a permission
      1. You could also alternatively use a management certificate
    2. If you want to call Resource Management API, then add the permissions needed to the service principal through the new Portal
  2. If you chose the delegated way for Service Management API (the first option), then you will have to either:
    1. Have the user authenticate against Azure AD with the Authorization Code Grant flow
    2. Or get the access token using the Password grant flow (you can see an example of this in another answer
  3. If instead you chose a management certificate or giving the permissions to the service principal, then you can get the access token directly from Azure AD using the Client credentials grant flow

In the end you will always end up with an access token that you can use for calling the API.

like image 43
juunas Avatar answered Sep 29 '22 10:09

juunas