Skip Navigation

A .NET Core 2.x simple daemon console application calling the graph with its own identity

Last updated: 12/4/2018
Edit on GitHub

About this sample

Overview

This sample application shows how to use the Azure AD v2.0 endpoint to access the data of Microsoft business customers in a long-running, non-interactive process. It uses the OAuth 2 client credentials grant to acquire an access token, which can be used to call the Microsoft Graph and access organizational data

The app is a .NET Core 2.1 Console application. It gets the list of users in an Azure AD tenant by using Microsoft Authentication Library (MSAL) Preview for .NET to acquire a token.

Scenario

The console application:

  • gets a token from Azure AD in its own name (without a user)
  • and then calls the Microsoft Graph /users endpoint to get the list of user, which it then displays (as Json blob)

For more information on the concepts used in this sample, be sure to read the v2.0 endpoint client credentials protocol documentation.

A variation of this sample using a certificate instead of an application password is available below Variation: daemon application using client credentials with certificates

How to run this sample

To run this sample, you'll need:

  • Visual Studio 2017 or just the .NET Core SDK
  • An Internet connection
  • A Windows machine (necessary if you want to run the app on Windows)
  • An OS X machine (necessary if you want to run the app on Mac)
  • A Linux machine (necessary if you want to run the app on Linux)
  • An Azure Active Directory (Azure AD) tenant. For more information on how to get an Azure AD tenant, see How to get an Azure AD tenant
  • A user account in your Azure AD tenant. This sample will not work with a Microsoft account (formerly Windows Live account). Therefore, if you signed in to the Azure portal with a Microsoft account and have never created a user account in your directory before, you need to do that now.

Step 1: Clone or download this repository

From your shell or command line:

git clone https://github.com/Azure-Samples/active-directory-dotnetcore-daemon-v2.git`

or download and exact the repository .zip file.

Given that the name of the sample is pretty long, and so are the name of the referenced NuGet packages, you might want to clone it in a folder close to the root of your hard drive, to avoid file size limitations on Windows.

Step 2: Register the sample with your Azure Active Directory tenant

There is one project in this sample. To register it, you can:

  • either follow the steps in the paragraphs below (Step 2 and Step 3)
  • or use PowerShell scripts that:
    • automatically create for you the Azure AD applications and related objects (passwords, permissions, dependencies)
    • modify the Visual Studio projects' configuration files.

If you want to use this automation, read the instructions in App Creation Scripts

Choose the Azure AD tenant where you want to create your applications

As a first step you'll need to:

  1. Sign in to the Azure portal using either a work or school account or a personal Microsoft account.
  2. If your account gives you access to more than one tenant, select your account in the top right corner, and set your portal session to the desired Azure AD tenant (using Switch Directory).
  3. In the left-hand navigation pane, select the Azure Active Directory service, and then select App registrations (Preview).

Register the client app (daemon-console)

  1. In App registrations (Preview) page, select New registration.
  2. When the Register an application page appears, enter your application's registration information:
    • In the Name section, enter a meaningful application name that will be displayed to users of the app, for example daemon-console.
    • In the Supported account types section, select Accounts in this organizational directory only ({tenant name}).
    • In the Redirect URI (optional) section, select Web in the combo-box. > Even if this is a desktop application, this is a confidential client application hence the Application Type being 'Web', which might seem counter intuitive.
    • For the Redirect URI*, enter https://<your_tenant_name>/daemon-console, replacing <your_tenant_name> with the name of your Azure AD tenant.
    • Select Register to create the application.
  3. On the app Overview page, find the Application (client) ID value and record it for later. You'll need it to configure the Visual Studio configuration file for this project.
  4. From the Certificates & secrets page, in the Client secrets section, choose New client secret:

    • Type a key description (of instance app secret),
    • Select a key duration of either In 1 year, In 2 years, or Never Expires.
    • When you press the Add button, the key value will be displayed, copy, and save the value in a safe location.
    • You'll need this key later to configure the project in Visual Studio. This key value will not be displayed again, nor retrievable by any other means, so record it as soon as it is visible from the Azure portal.
  5. In the list of pages for the app, select API permissions

    • Click the Add a permission button and then,
    • Ensure that the Microsoft APIs tab is selected
    • In the Commonly used Microsoft APIs section, click on Microsoft Graph
    • In the Application permissions section, ensure that the right permissions are checked: User.Read.All
    • Select the Add permissions button
  6. At this stage permissions are assigned correctly but the client app does not allow interaction. Therefore no consent can be presented via a UI and accepted to use the service app. Click the Grant/revoke admin consent for {tenant} button, and then select Yes when you are asked if you want to grant consent for the requested permissions for all account in the tenant. You need to be an Azure AD tenant admin to do this.

Step 3: Configure the sample to use your Azure AD tenant

In the steps below, "ClientID" is the same as "Application ID" or "AppId".

Open the solution in Visual Studio to configure the projects

Configure the client project

  1. Open the daemon-console\appsettings.json file
  2. Find the app key Tenant and replace the existing value with your Azure AD tenant name.
  3. Find the app key ClientId and replace the existing value with the application ID (clientId) of the daemon-console application copied from the Azure portal.
  4. Find the app key ClientSecret and replace the existing value with the key you saved during the creation of the daemon-console app, in the Azure portal.

Step 4: Run the sample

Clean the solution, rebuild the solution, and run it. You might want to go into the solution properties and set both projects as startup projects, with the service project starting first.

Start the application, it will display the users in the tenant.

About the code

The relevant code for this sample is in the Program.cs file, in the RunAsync() method. The steps are:

  1. Create the MSAL confidential client application.

    Important note: even if we are building a console application, it is a daemon, and therefore a confidential client application, as it does not access Web APIs on behalf of a user, but on its own application behalf.

    ClientCredential clientCredentials = new ClientCredential(config.ClientSecret);
    var app = new ConfidentialClientApplication(config.ClientId, config.Authority, 
                                                "https://daemon", clientCredentials, null, new TokenCache());
    
    
  2. Define the scopes.

Specific to client credentials, you don't specify, in the code, the individual scopes you want to access. You have statically declared them during the application registration step. Therefore the only possible scope is "resource/.default" (here "https://graph.microsoft.com/.default") which means "the static permissions defined in the application"

```CSharp
// With client credentials flows the scopes is ALWAYS of the shape "resource/.default", as the 
// application permissions need to be set statically (in the portal or by PowerShell), and then granted by
// a tenant administrator
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
```
  1. Acquire the token

    AuthenticationResult result = null;
    try
    {
        result = await app.AcquireTokenForClientAsync(scopes);
    }
    catch(MsalServiceException ex)
    {
        // AADSTS70011
        // Invalid scope. The scope has to be of the form "https://resourceurl/.default"
        // Mitigation: this is a dev issue. Change the scope to be as expected
    }
    
  2. Call the API

    In that case calling "https://graph.microsoft.com/v1.0/users" with the access token as a bearer token.

Troubleshooting

If you get an error when calling the API that the application identity could not be determined, this is because the tenant administrator has not granted permissions to the application. See step 6 of Register the client app (daemon-console) above

Variation: daemon application using client credentials with certificates

Daemon applications can use two forms of secrets to authenticate themselves with Azure AD:

  • application secrets (also named application password). This is what we've seen so far.
  • certificates. This is the object of this paragraph.

To use certificates instead of an application secret you will need to do little changes to what you have done so far:

  • (optionnally) generate a certificate and export it, if you don't have one already
  • register the certificate with your application in the application registration portal
  • enable the sample code to use certificates instead of app secret.

(Optional) Create a self-signed certificate

To complete this step, you will use the New-SelfSignedCertificate Powershell command. You can find more information about the New-SelfSignedCertificat command here.

  1. Open PowerShell and run New-SelfSignedCertificate with the following parameters to create a self-signed certificate in the user certificate store on your computer:

    $cert=New-SelfSignedCertificate -Subject "CN=DaemonConsoleCert" -CertStoreLocation "Cert:\CurrentUser\My"  -KeyExportPolicy Exportable -KeySpec Signature
    
  2. Export this certificate using the "Manage User Certificate" MMC snap-in accessible from the Windows Control Panel. You can also add other options to generate the certificate in a different store such as the Computer or service store (See How to: View Certificates with the MMC Snap-in).

Alternatively you can use an existing certificate if you have one (just be sure to record its name for the next steps)

Add the certificate for the daemon-console application in Azure AD

In the application registration blade for your application, in the Certificates & secrets page, in the Certificates section:

  1. Click on Upload certificate and, in click the browse button on the right to select the certificate you just exported (or your existing certificate)
  2. Click Add

Configure the Visual Studio project

To change the visual studio project to enable certificates you need to:

  1. Open the daemon-console\appsettings.json file
  2. Find the app key CertificateName and replace the existing value with the name of your certificate (if you generated your own certificate from the instructions above, this should be CN=DaemonConsoleCert).
  3. Right click on the project in VisualStudio, and in the Build tab, add a Conditional compilation symbol set to VariationWithCertificateCredentials. This is to enable conditional compilation for your project to use the certificate rather than the app secret.

Build and run

Build and run your project. You have the same output, but this time, your application is authenticated with Azure AD with the certificate instead of the application secret.

About the alternate code

The code change is the following: the ClientCredentials instance passed to the constructor of the ConfidentialClientApplication is now built from a ClientAssertionCertificate instance (built from the certificate) instead of from the application password

clientCredentials = new ClientCredential(new ClientAssertionCertificate(certificate));
var app = new ConfidentialClientApplication(config.ClientId, config.Authority,
                                            "https://daemon", clientCredentials, null, new TokenCache());

The rest of the application is the same. The sample also has a method to retrive the certificate from the Windows certificate store (This part was not tested on linux)

Community Help and Support

We use Stack Overflow with the community to provide support. We highly recommend you ask your questions on Stack Overflow first and browse existing issues to see if someone has asked your question before. Make sure that your questions or comments are tagged with [msal.dotnet].

If you find a bug in the sample, please raise the issue on GitHub Issues.

If you find a bug in msal.Net, please raise the issue on MSAL.NET GitHub Issues.

To provide a recommendation, visit the following User Voice page.

Contributing

If you'd like to contribute to this sample, see CONTRIBUTING.MD.

This project has adopted the Microsoft Open Source Code of Conduct. For more information, see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

More information

For more information, see MSAL.NET's conceptual documentation:

For more information about the underlying protocol:

For a more complex multi-tenant Web app daemon application, see active-directory-dotnet-daemon-v2