In past few articles, we have seen how to setup applications which calls web APIs. In most of those posts, we have used Delegated permissions, meaning, the API would be accessed by application on behalf of signed in users.
In this article, let’s have look at how a daemon app can call an API which is protected using Azure AD. We are going to use MSAL.NET for this demo.
What is Daemon App ?
Below is the definition from the wikipedia:
In multitasking computer operating systems, a daemon is a computer program that runs as a background process, rather than being under the direct control of an interactive user.
So what are we going to do is we will create a console application that calls a web API protected using Azure AD.
Create a Web API
We will have to register the API application in Azure AD. Then we will have to configure our web API application to use appropriate
Client ID and
Tenant ID. Also, we will have to configure middleware to allow only authenticated / authorized users to call the APIs.
Refer my blog article about securing web APIs for detailed steps.
API Application Permissions
The above steps will setup the app registration for the API app. By default, when you create the scope as mentioned in above section, it creates scope which can be used only for Delegated Permissions.
When Daemon app executes, nobody needs to sign in. Daemon apps don’t interact with users. Delegated permissions wouldn’t make sense. The App needs to call the API using Application Permissions. For exposing API with Application permissions, you need to follow below steps.
Login to Azure Portal and go to Azure Active Directory from left navigation menu. Then go to the App registrations menu to open the API’s app registration entry.
Then select the manifest option from the panel. In the manifest find the entry of
appRoles. This node should be an empty JSON array.
Now, in that empty array, add an entry as shown below. Make sure that:
valuedo not contain spaces
idis set to unique GUID
allowedMemberTypesis set to Application only
Then hit the Save button to save the modification.
Daemon App Registration
Sign in to Azure portal and go to the Azure Active Directory option from the left navigation. Next, go to App registrations and then click on New registration to register the daemon app in Azure.
Three inputs are required on this page:
- Name, for the app registration
- Supported account types, first option means only accounts from current tenant can be used. This is most suitable option. If you want to use any account from any tenant under current organization , you can select second option.
- Platform configuration, select background process and automation (daemon) application.
Once this is done click on Register to complete the registration.
Daemon App Client Secret
Our background app is going to call an API, protected by Azure AD. Also, as it is a background app, it is going to run on a single server and will not be distributed to publicly.
So, this becomes a confidential client application. This also means we will need client secret to prove our application’s identity.
So, open the newly created Sample Daemon App registration and then go to the Certificates and secrets view.
Under client secrets section, click on New client secret to create new one. It will ask for the name and the expiry duration. Provide any display name (e.g. First Secret) and set expiry duration to 1 year.
Copy and note down the client secret’s value as it will not be shown again there. Keep it at safe place. We will need it while configuring the daemon application.
Daemon App API Permissions
Now, select the API Permissions from the daemon app registration. Then click on Add a permission button. This will open a new panel on right side. On the new panel, select My APIs tab and select
SampleWebApi from the list.
On next screen, select Application Permissions and then select
access_as_application scope and click on Add permissions button.
Here, you also need to grant the admin consent for the tenant.
Create Console Application
Create a .NET Core console application using Visual Studio. Below are the steps that you need to follow to get the working application. The steps explain the dependencies, the configurations and core code to get the access tokens.
Add below NuGet packages to the console application:
Add a JSON file with name
appsettings.json in the console application. In this file, the Azure AD application configurations (i.e. client id, authority, client secret or certificate name) details are configured.
In addition to this, the scopes required to call our API and the API URL are also configured in this file. Below is how the file with settings should look:
Below method reads these configuration settings and populate the concrete classes.
This component will instantiate the ConfidentialClientApplication instance. This instance will either be created using client secret (which is used in this demo) or using certificates.
Then the bootstrapper requests the access token from the authority using AcquireTokenForClient API, which uses client credentials flow to get the access token for the client.
If the scopes are specified correctly, then the bootstrapper should return the AuthenticationResult which contains the
access token. Please note this call will not return id token.
Next thing is to use the
access token to call the intended API. The below code shows complete code of a class which calls bootstrapper to get the token and then uses token to call the API.
Run and Verify
Now, when both console application and API applications are started, the console application prints the JSON result returned from API as shown below.
You can have look at all the MSAL samples in my GitHub repository.
I hope you enjoyed this post. Let me know your thoughts.
This Post Has 3 Comments
Pingback: Creating Custom Login Page in Azure AD B2C – The Code Blogger
Can these apps get user specific data? Such as viewing a calendar for 1 user? Or no since no user needs to sign in?
Hey Kurt, I am not sure if I understood your question correctly. But as you see, we are using access as application permission, it may not be possible to get user specific data. To be frank, I have not tried it as such (yet).