0
votes

This question directly follows this one. I have a native app wich has to display the groups the user is a member of (more precisely, I want to display the sharepoint site associated to the group).

It works well with any user of the tenant the app is registered on. But when I try to connect from another tenant, it only works with an admin account. Trying to connect with a user account gives me this error :

Correlation ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx

Timestamp: 2017-04-19 08:32:24Z

AADSTS90093: Calling principal cannot consent due to lack of permissions.

The admin consent flow is never triggered. As stated in my previous post linked above, trying to add "prompt=admin_consent" as a query parameter returns this error :

"Duplicate query parameter 'prompt' in extraQueryParameters"

The samples and tutorials I've found so far were all aimed toward web apps and the questions that could have helped me on stackoverflow are strangely silent once this problem is mentionned link1 link2.


Is there even a way to trigger admin consent flow for a native app? Can it be done using ADAL or another way?

Changing the app from native to web is not an option, as I am only trying to add a new feature to an existing app.
So if the answer to the above question is 'no', is there any workaround? I'm open to any suggestions.

1

1 Answers

2
votes

You could send the admin consent reuquest without using ADAL . Since you are using WinForm app , we could use WebBrowser control to show the login page , set prompt=admin_consent as part of the request url .If admin consent success, check whether value of admin_consent in response is True. Code below is for your reference:

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {

        var parameters = new Dictionary<string, string>
            {
                { "response_type", "code" },
                { "client_id", "<client id>" },
                { "redirect_uri", "http://localhost" },
                { "prompt", "admin_consent"}
            };
        var requestUrl = string.Format("{0}/authorize?{1}", "https://login.microsoftonline.com/common/oauth2", BuildQueryString(parameters));
        webBrowser1.Navigate(requestUrl);
    }
    protected string EndPointUrl
    {
        get
        {
            return string.Format("{0}/{1}", "https://login.microsoftonline.com/common", "");
        }
    }

    private string BuildQueryString(IDictionary<string, string> parameters)
    {
        var list = new List<string>();

        foreach (var parameter in parameters)
        {
            list.Add(string.Format("{0}={1}", parameter.Key, Uri.EscapeDataString(parameter.Value)));
        }

        return string.Join("&", list);
    }

    private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        if (e.Url.AbsoluteUri.StartsWith("http://localhost"))
        {
            var collection = System.Web.HttpUtility.ParseQueryString(e.Url.Query);
            //check whether admin consent success 
            if (collection["admin_consent"] == "True")
            {
                //hide/close webBrowser
            }

        }
    }

If you don't want to do anything with code , the tenant admin could do admin consent manually by opening a browser, and going to the following URL :

https://login.microsoftonline.com/<tenant>/oauth2/authorize?client_id=<client id>&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2F&nonce=1234&resource=https%3A%2F%2Fgraph.windows.net%2F&prompt=admin_consent