How to get On-Behalf-Of-User token in .NET using ADAL

Viewed 4822

I have created an Azure AAD app of type webapp which has client secret and redirect url. Now, I want to get an access token on behalf of user using the AAD app. From looking at the documentation, I got the following code so far.

    static void Main(string[] args)
    {
        var clientId = "<REDACTED>";
        var clientSecret = "<REDACTED>";
        var resourceAppIdURI = "https://api.office.com/discovery/";
        var authority = "https://login.microsoftonline.com/common";

        AuthenticationContext ac = new AuthenticationContext(authority, new FileCache());
        ClientCredential cc = new ClientCredential(clientId, clientSecret);

        // Get token as application
        var task = ac.AcquireTokenAsync(resourceAppIdURI, cc);
        task.Wait();
        var appToken = task.Result.AccessToken;

        // Get tokenn on behalf of user
        UserCredential uc = new UserCredential("usrname@mytenant.com");
        task = ac.AcquireTokenAsync(resourceAppIdURI, clientId, uc);
        var userToken = task.Result.AccessToken;

        Console.ReadLine();
    }

But this is the error I get when I try to get user token is as follows.

Message "AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.\r\nTrace ID: 0e977f67-d5cb-4cf5-8fea-bac04b6d0400\r\nCorrelation ID: 824a96bf-8007-4879-970c-2680644b8669\r\nTimestamp: 2017-07-21 05:02:41Z" string

Why am I getting this error and how to fix it? Do I need to login with the user first and then use UserAssertion instead ? There are tonnes of overloaded methods for AcquireTokenAsync method, but not sure what I should use.

I also looked at this github url to see how they are doing it https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof/blob/8afb3e6a648d8e7246685bf6747d009006c761b8/TodoListService/Controllers/TodoListController.cs

This is the relevant code to get token as logged in user

    ClientCredential clientCred = new ClientCredential(clientId, appKey);
    var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
    string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
    string userAccessToken = bootstrapContext.Token;
    UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);

    string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
    string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
    AuthenticationContext authContext = new AuthenticationContext(authority, new DbTokenCache(userId));

Here they already have a logged in user and creating a UserAssertion from that loggedin user's token. In my console app, the user hasn't logged in yet. So I need a way to do this in my console app. How can I show the AAD login page to the user as a pop-up and then once the user enters creds use that info to create an UserAssertion object?

thanks

1 Answers
Related