Skip to content

Latest commit

 

History

History
157 lines (111 loc) · 4.94 KB

scenario-daemon-call-api.md

File metadata and controls

157 lines (111 loc) · 4.94 KB
title description author manager ms.author ms.custom ms.date ms.reviewer ms.service ms.topic
How to call a downstream web API from a daemon app
Learn how to build a daemon app that calls a web API.
Dickson-Mwendia
CelesteDG
dmwendia
02/01/2024
jmprieur
identity-platform
concept-article

How to call a downstream web API from a daemon app

.NET daemon apps can call a web API. .NET daemon apps can also call several preapproved web APIs.

Calling a web API from a daemon application

Here's how to use the token to call an API:

Microsoft.Identity.Web abstracts away the complexity of MSAL.NET. It provides you with higher-level APIs that handle the internals of MSAL.NET for you, such as processing Conditional Access errors, caching.

Here's the Program.cs of the daemon app calling a downstream API:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;

// In the Program.cs, acquire a token for your downstream API

var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddDownstreamApi("MyApi",
    tokenAcquirerFactory.Configuration.GetSection("MyWebApi"));
var sp = tokenAcquirerFactory.Build();

var api = sp.GetRequiredService<IDownstreamApi>();
var result = await api.GetForAppAsync<IEnumerable<TodoItem>>("MyApi");
Console.WriteLine($"result = {result?.Count()}");

Here's the Program.cs of a daemon app that calls Microsoft Graph:

var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddMicrosoftGraph();
var serviceProvider = tokenAcquirerFactory.Build();
try
{
    GraphServiceClient graphServiceClient = serviceProvider.GetRequiredService<GraphServiceClient>();
    var users = await graphServiceClient.Users
        .GetAsync(r => r.Options.WithAppOnly());
    Console.WriteLine($"{users.Count} users");
    Console.ReadKey();
}
catch (Exception ex) { Console.WriteLine("We could not retrieve the user's list: " + $"{ex}"); }
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// Set the appropriate header fields in the request header.
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
conn.setRequestProperty("Accept", "application/json");

String response = HttpClientHelper.getResponseStringFromConn(conn);

int responseCode = conn.getResponseCode();
if(responseCode != HttpURLConnection.HTTP_OK) {
    throw new IOException(response);
}

JSONObject responseObject = HttpClientHelper.processResponse(responseCode, response);

Using an HTTP client like Axios, call the API endpoint URI with an access token as the authorization bearer.

const axios = require('axios');

async function callApi(endpoint, accessToken) {

    const options = {
        headers: {
            Authorization: `Bearer ${accessToken}`
        }
    };

    console.log('request made to web API at: ' + new Date().toString());

    try {
        const response = await axios.default.get(endpoint, options);
        return response.data;
    } catch (error) {
        console.log(error)
        return error;
    }
};
endpoint = "url to the API"
http_headers = {'Authorization': 'Bearer ' + result['access_token'],
                'Accept': 'application/json',
                'Content-Type': 'application/json'}
data = requests.get(endpoint, headers=http_headers, stream=False).json()

[!INCLUDE Call web API in .NET]


Calling several APIs

For daemon apps, the web APIs that you call need to be preapproved. There's no incremental consent with daemon apps. (There's no user interaction.) The tenant admin needs to provide consent in advance for the application and all the API permissions. If you want to call several APIs, acquire a token for each resource, each time calling AcquireTokenForClient. MSAL uses the application token cache to avoid unnecessary service calls.

Next steps

Move on to the next article in this scenario, Move to production.

Move on to the next article in this scenario, Move to production.

Move on to the next article in this scenario, Move to production.

Move on to the next article in this scenario, Move to production.

Move on to the next article in this scenario, Move to production.