kijoke
kijoke

Reputation: 11

Azure function Graph API Insufficient privileges

I've created a C# function in Azure and it looks like this:

using System;
using System.Net;
using System.Net.Http.Headers;
using System.Collections.Specialized;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;
using System.Text;
using Newtonsoft.Json.Linq;

public static async void Run(string input, TraceWriter log)
{

    log.Info("---- Gestartet ----");
    var token = await HttpAppAuthenticationAsync();
    log.Info("---- Token: " + token.ToString());

    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var user = "[email protected]";
    var userExists = await DoesUserExistsAsync(client, user, log);

    if(userExists)
    {
        log.Info("Der Benutzer existiert.");
    }
    else {
        log.Info("Benutzer nicht gefunden.");
    }
}

public static async Task<string> HttpAppAuthenticationAsync()
{
    //log.Info("---- Start ----");

    //  Constants
    var tenant = "2XXXXXCC6-c789-41XX-9XXX-XXXXXXXXXX";
    var resource = "https://graph.windows.net/";
    var clientID = "5XXXXef-4905-4XXf-8XXa-bXXXXXXX2";
    var secret = "5GFzeg6VyrkJYUJ8XXXXXXXeKbjYaXXX7PlNpFkkg=";

    var webClient = new WebClient();

    var requestParameters = new NameValueCollection();

    requestParameters.Add("resource", resource);
    requestParameters.Add("client_id", clientID);
    requestParameters.Add("grant_type", "client_credentials");
    requestParameters.Add("client_secret", secret);

    var url = $"https://login.microsoftonline.com/{tenant}/oauth2/token";
    var responsebytes = await webClient.UploadValuesTaskAsync(url, "POST", requestParameters);
    var responsebody = Encoding.UTF8.GetString(responsebytes);
    var obj = JsonConvert.DeserializeObject<JObject>(responsebody);
    var token = obj["access_token"].Value<string>();
    //log.Info("HIER: " + token);
    return token;
}

private static async Task<bool> DoesUserExistsAsync(HttpClient client, string user, TraceWriter log)
{
    log.Info("---- Suche Benutzer ----");
    try
    {
        var payload = await client.GetStringAsync($"https://graph.microsoft.net/v1.0/users/user");

        return true;
    }
    catch (HttpRequestException)
    {

        return false;
    }
}

In my log I get the bearer token. But then result of DoesUserExistsAsync is false. If I send an request via Postman with the token I get following response:

{
    "error": {
        "code": "Authorization_RequestDenied",
        "message": "Insufficient privileges to complete the operation.",
        "innerError": {
            "request-id": "10XXX850-XXX-4d72-b6cf-78X308XXXXX0",
            "date": "2017-09-07T14:03:58"
        }
    }
}

In the Azure AD I created an App and the permissions are: Function with allowd Azure AD login

Permisions for function-app

(I gave all permisions only to test what`s wrong)

Upvotes: 1

Views: 253

Answers (1)

Marc LaFleur
Marc LaFleur

Reputation: 33094

Since you're using client_credentials, there is no "user". That OAUTH grant only authenticates your application, not an actual user.

When using client_credentials, only the scopes listed under "Application Permissions" are applicable. Since you don't have a user authenticated, there isn't a user to "delegate" to your app.

Application Permissions are also unique in that every one of them requires Admin Consent before your app can use them. Without consent, your application will have insufficient privileges to complete any operation.

Also, this call won't return anything:

await client.GetStringAsync($"https://graph.microsoft.net/v1.0/users/user");

I assume what you're really looking for is:

private async Task<bool> DoesUserExistsAsync(HttpClient client, string userPrincipalName, TraceWriter log)
{
    log.Info("---- Suche Benutzer ----");
    try
    {
        var payload = await client.GetStringAsync($"https://graph.microsoft.net/v1.0/users/" 
                                                  + userPrincipalName);
        return true;
    }
    catch (HttpRequestException)
    {
        return false;
    }
}

Upvotes: 1

Related Questions