8
votes

I need to call Microsoft Graph API to create user in Azure AD.

First I need to test from console application and then need to implement in Azure function.

https://developer.microsoft.com/en-us/graph/graph-explorer

I am new to Microsoft Graph API , How can I connect and execute API from c# console application.

I have already registered the application in AAD.

I am trying to acquire token as :

string resourceId = "https://graph.microsoft.com";
string tenantId = "<tenantID>";
string authString = "https://login.microsoftonline.com/" + tenantId;
string upn = String.Empty;
string clientId = "<ClientID>";
string clientSecret = "<clientSecret>";
//string clientSecret = ConfigurationManager.AppSettings["clientSecret"];


log.Verbose("ClientSecret=" + clientSecret);
log.Verbose("authString=" + authString);

var authenticationContext = new AuthenticationContext(authString, false);

// Config for OAuth client credentials 
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(resourceId,clientCred);
string token = authenticationResult.AccessToken;
log.Verbose("token=" + token);

I trying to use existing AADB2C. b2c-extensions-app. Do not modify. Used by AADB2C for storing user data.

I have enabled permission as: enter image description here

I neither get exception nor get access token and program silently exit

Also :

There is new library

 <package id="Microsoft.Identity.Client" version="1.1.0-preview" targetFramework="net46" />

How can I direct login without login pop-up with the following and acquire token ? PublicClientApplication

5
@MurrayFoxcroft You are confusing Facebook Graph with Microsoft Graph. These are two distinct APIs from separate vendors. - Marc LaFleur

5 Answers

11
votes

In order to connect from a console app, you'll need to first obtain a valid token. Since you lack a UI, you'll want to Get access without a user. Note that this type of "app-only" token requires Administrative Consent before it can be used.

In order to support the Create User scenario, you will need to ensure your permission scopes include User.ReadWrite.All.

Once you have a valid token you can make calls into the Graph API. Graph is a REST API so all calls are made over HTTP with the token passed within the Authorization Header.

You can read a general overview at Get started with Microsoft Graph and REST. There are also several language/framework specific overviews available but all of them assume you have a UI (i.e. not simply console). Generally speaking, if you're looking for a console tool for creating users you may prefer using PowerShell.

10
votes

I assume that you already have Azure AD application with granted Administrative Consent.

In order to connect from a console app, you'll need to first obtain a valid token. Since you lack a UI, you'll want to Get access without a user. Note that this type of "app-only" token requires Administrative Consent before it can be used.

Then you have to add two NuGet dependencies to your dotnet project

<PackageReference Include="Microsoft.Graph" Version="1.15.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.0.0" />

Microsoft.Identity.Client for authentication using Azure AD and Microsoft.Graph for executing MS Graph queries.

var tenantId = "you-azure-tenand-id";
var clientId = "azure-ad-application-id";
var clientSecret = "unique-secret-generated-for-this-console-app";

// Configure app builder
var authority = $"https://login.microsoftonline.com/{tenantId}";
var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithClientSecret(clientSecret)
    .WithAuthority(new Uri(authority))
    .Build(); 

// Acquire tokens for Graph API
var scopes = new[] {"https://graph.microsoft.com/.default"};
var authenticationResult = await app.AcquireTokenForClient(scopes).ExecuteAsync();

// Create GraphClient and attach auth header to all request (acquired on previous step)
var graphClient = new GraphServiceClient(
    new DelegateAuthenticationProvider(requestMessage => {
        requestMessage.Headers.Authorization = 
            new AuthenticationHeaderValue("bearer", authenticationResult.AccessToken);

        return Task.FromResult(0);
    }));

// Call Graph API
var user = await graphClient.Users["[email protected]"].Request().GetAsync()

Update 2020.01

There is a new package Microsoft.Graph.Auth that simplify auth and token management.

Let's say you want to use some Beta API this time.

<PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.2" />
<PackageReference Include="Microsoft.Graph.Beta" Version="0.12.0-preview" />
var tenantId = "you-azure-tenand-id";
var clientId = "azure-ad-application-id";
var clientSecret = "unique-secret-generated-for-this-console-app";

// Configure application
var clientApplication = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .WithClientSecret(clientSecret)
    .Build();

// Create ClientCredentialProvider that will manage auth token for you
var authenticationProvider = new ClientCredentialProvider(clientApplication);
var graphClient = new GraphServiceClient(authenticationProvider);

// Call Graph API
var user = await graphClient.Users["[email protected]"].Request().GetAsync()
1
votes

This question is rather old, but it was one of the first questions that popped up when I initially needed to do the same thing. Below I will document the steps and resources I used to make it happen:

  1. I used an O365 tenant (you can get one from office.com - note that you can get a one year developer trial). Once you have a tenant, you also have access to Azure portal if you log in as your tenant admin user. Under Azure Portal, go to Active Directory/properties to see the tenant ID.
  2. I followed the instructions here https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-netcore-daemon to create a new registered application. I created a new secret and copied the value (that will be client secret in your console app). The registered application id will be the client ID in your console app.
  3. I cloned the github repo in the above link and changed the values in the appsettings to the tenant ID, client ID, and client secret noted in the steps above.
  4. The code in that repo has some methods called which no longer exist in ConfigurationBuilder as of .NETCore 2.1. I substituted these lines (there's probably a better / shorter way):

    authenticationConfig.Tenant = Configuration.GetSection("Tenant").Value.ToString(); authenticationConfig.ClientId = Configuration.GetSection("ClientId").Value.ToString(); authenticationConfig.ClientSecret = Configuration.GetSection("ClientSecret").Value.ToString();

  5. You should now be iterating through users in your tenant. You can go to the graph explorer ( https://developer.microsoft.com/en-us/graph/graph-explorer ) to find more URLs (find the line in Program.cs to substitute them). As far as I know so far, v2.0 of the API is "beta" (put "beta" where "v1.0" is - someone please correct me if I'm wrong).

    await apiCaller.CallWebApiAndProcessResultASync("https://graph.microsoft.com/v1.0/users", result.AccessToken, Display);

0
votes

This MSAL console app tutorial describes getting a token using MSAL (Microsoft Authentication Library) in a .NET console app.

To make a Microsoft Graph call, I replaced the RunAsync() function with this, which attaches the acquired token to the requests with the GraphServiceClient:

static async Task RunAsync()
    {
        const string clientId = "your client id";
        string[] scopes = { "User.Read" };
        AuthenticationResult result;

        var clientApp = new PublicClientApplication(clientId);
        try
        {
            result = await clientApp.AcquireTokenAsync(scopes.Split(new char[] { ' ' }));
            Console.WriteLine(result.AccessToken);
            GraphServiceClient graphClient = new GraphServiceClient(
                new DelegateAuthenticationProvider(
                    async (requestMessage) =>
                    {
                        // Append the access token to the request.
                        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken);

                        // Some identifying header
                        requestMessage.Headers.Add("SampleID", "aspnet-connect-sample");
                    }));

            // Get a page of mail from the inbox
            var inboxMail = await graphClient.Me.MailFolders.Inbox.Messages.Request().GetAsync();
            foreach(var mail in inboxMail.CurrentPage.ToList())
            {
                Console.Write("From: {0}\nSubject: {1}\nBody:\n{2}\n--------------------\n", mail.From.EmailAddress.Address, mail.Subject, mail.BodyPreview);
            }
        }

        // Unable to retrieve the access token silently.
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
0
votes

Note

You must use the Azure AD Graph API to manage users in an Azure AD B2C directory. This is different from the Microsoft Graph API. Learn more here.

There's a pretty good sample project @ GitHub: AzureADQuickStarts/B2C-GraphAPI-DotNet and it's accompanying documentation here.