9

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;
}
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
stephen robinson
  • 91
  • 1
  • 1
  • 3

4 Answers4

11

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.

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

BrewMate
  • 1,010
  • 5
  • 15
  • Hide exception without logging and just return null is not a good style – Michael Freidgeim Aug 03 '17 at 00:37
  • I agree, it was just for simplicity in the sample. I typically make my own response class depending on the app that will allow me to handle errors gracefully. – BrewMate Aug 07 '17 at 21:10
  • @BrewMate How do you solve ADAL auth problem on Xamarin Android where device is rotated btw screen prompt for user-email and 2nd prompt for password. If on that 2nd prompt user rotates device, they are returned back and reprompted for user-email again. https://stackoverflow.com/questions/56813381/azure-ad-adal-login-screen-loses-entered-user-email-on-device-orientation-in-a/56847697#56847697 – pixel Jul 03 '19 at 16:04
  • where is ResourceID used in this answer? I only see resource in the code. – L0uis Aug 01 '19 at 22:54
  • Hey, on UWP when I try the line ` var platformParams = new PlatformParameters(PromptBehavior.Auto);` it wants a second paramter as well, of customWebUi. Do you know what should be here? – PMO1948 Oct 26 '22 at 09:55
2

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.

Community
  • 1
  • 1
juunas
  • 54,244
  • 13
  • 113
  • 149
0

IF you're using the wrappers, ensure to have the correct version-Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.21.301221612. Once referenced, you can run this below. For alternatives, see this blog: https://samtran.me/2018/11/11/power-bi-rest-api/

Sam Tran
  • 148
  • 1
  • 3
0

If you are also running into issue on Android where device rotation returns you back to prompt for user email, you can follow up progress of fixes for both ADAL and MSAL here:

https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/1622 https://github.com/xamarin/xamarin-android/issues/3326

pixel
  • 9,653
  • 16
  • 82
  • 149