Back Articles

Microsoft Entra App Registrations: Client Credentials, App Roles, and Workload Identity Federation / Step 3 of 5

Request and inspect an access token

Let’s create a simpel .NET console application that obtains a token using MSAL.

Create .NET console application

Open VS Code in a new working folder. Open the terminal using CTRL + ` . Then enter dotnet new console -f net10.0. Next, add the MSAL library by running dotnet package add Microsoft.Identity.Client.

Open Program.cs and modify it as follows:

using Microsoft.Identity.Client;

var tenantid = "8bd3e25a-60bf-409f-b972-83f05d7da3f3";

// This refers to the books reader client application app registration
var clientid = "f27b2359-fecd-402b-93bb-7873b4b645d6";
var clientsecret = "<client-secret>";

// Add /.default scope to the API's URI;
// This refers to the back-end API app registration
var scopes = new[]
{
    "api://46ce9c55-e894-4cc0-ae2c-efe0fc8b0caf/.default"
};

var app = ConfidentialClientApplicationBuilder.Create(clientid)
    .WithClientSecret(clientsecret)
    .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantid}"))
    .Build();

var result = await app.AcquireTokenForClient(scopes).ExecuteAsync();

Console.WriteLine(result.AccessToken);

Of course substitute with your values. When running this program should output an access token to the console window.

Inspect the access token

The access token looks something like this:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImZFdHFyaEtUMWJYQUdhZlNkUW9OMXZYVFJwSSIsImtpZCI6ImZFdHFyaEtUMWJYQUdhZlNkUW9OMXZYVFJwSSJ9.
eyJhdWQiOiJhcGk6Ly80NmNlOWM1NS1lODk0LTRjYzAtYWUyYy1lZmUwZmM4YjBjYWYiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC84YmQzZTI1YS02MGJmLTQwO
WYtYjk3Mi04M2YwNWQ3ZGEzZjMvIiwiaWF0IjoxNzg2MjEzOTUxLCJuYmYiOjE3ODYyMTM5NTEsImV4cCI6MTc4NjIxNzg1MSwiYWlvIjoiazJGZ1lKaXd1RXh2UlhsZHRZK2
dUSVdLeTZrYU50R3NhNy9EK2o5R2RHcGE3M3NZbHdjQSIsImFwcGlkIjoiZjI3YjIzNTktZmVjZC00MDJiLTkzYmItNzg3M2I0YjY0NWQ2IiwiYXBwaWRhY3IiOiIxIiwiaWR
wIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOGJkM2UyNWEtNjBiZi00MDlmLWI5NzItODNmMDVkN2RhM2YzLyIsIm9pZCI6IjJjMTczODAwLTE4ZGMtNGU2MS04MTBjLWIz
MGZiZTg4ODIxMiIsInJoIjoiMS5BWE1BV3VMVGk3OWduMEM1Y29Qd1hYMmo4MVdjemthVTZNQk1yaXp2NFB5TERLOEFBQUJ6QUEuIiwicm9sZXMiOlsiQm9va3MuUmVhZCJdL
CJzdWIiOiIyYzE3MzgwMC0xOGRjLTRlNjEtODEwYy1iMzBmYmU4ODgyMTIiLCJ0aWQiOiI4YmQzZTI1YS02MGJmLTQwOWYtYjk3Mi04M2YwNWQ3ZGEzZjMiLCJ1dGkiOiJyc1
R4aExGWktVS0tCM2FMTGh3TUFBIiwidmVyIjoiMS4wIiwieG1zX2Z0ZCI6IkJBaFlwaUIxQTh6WFRIN2c1aER1anNEcTlZdWJrR05CN3ZjMW1rRmR5TGNCWm5KaGJtTmxZeTF
rYzIxeiJ9.gaJcknuWEZD_YdV2D2ysqQy1w2VnP6i_xNWytdd031C5TziqSR6jC7MEM224oL5hOOKX1sKERZQt92yb18AOA45taPefc_4AltM1qjb1yeptl9fDOEYy14R986P
yTkuLnZh1U gBU5O6DNzlIeAAeTPOSyWxdUrNyrdvOdgtX9dCXGQkKFrYLm1IGIi_UAN2n6ehOniHaMEB_qZOUxODi9b0PHnC0BCL4sYlmUXEY9OlW0J-S8G3_AiNQjccczKy
2v693zeaxbJwGkQgnU5oPdF-r0CTVZjzff6Z9eqWmjQa839n66mSEpzRnyFEhQcYSx-6UeCV3pt-J14S0fDp_yw

This is a JWT carrying authenticated (signed) information. For more information on JWTs, see JWT.io. Let’s decode the payload.

{
  "aud": "api://46ce9c55-e894-4cc0-ae2c-efe0fc8b0caf",
  "iss": "https://sts.windows.net/8bd3e25a-60bf-409f-b972-83f05d7da3f3/",
  "iat": 1786213951,
  "nbf": 1786213951,
  "exp": 1786217851,
  "aio": "k2FgYJiwuExvRXldtY+gTIWKy6kaNtGsa7/D+j9GdGpa73sYlwcA",
  "appid": "f27b2359-fecd-402b-93bb-7873b4b645d6",
  "appidacr": "1",
  "idp": "https://sts.windows.net/8bd3e25a-60bf-409f-b972-83f05d7da3f3/",
  "oid": "2c173800-18dc-4e61-810c-b30fbe888212",
  "rh": "1.AXMAWuLTi79gn0C5coPwXX2j81WczkaU6MBMrizv4PyLDK8AAABzAA.",
  "roles": [
    "Books.Read"
  ],
  "sub": "2c173800-18dc-4e61-810c-b30fbe888212",
  "tid": "8bd3e25a-60bf-409f-b972-83f05d7da3f3",
  "uti": "rsTxhLFZKUKKB3aLLhwMAA",
  "ver": "1.0",
  "xms_ftd": "BAhYpiB1A8zXTH7g5hDujsDq9YubkGNB7vc1mkFdyLcBZnJhbmNlYy1kc21z"
}

Important claims are:

  • aud: refers to audience; who this token is meant for. This refers to the back-end API app registration. Ultimately, this means that the access token will (or should) only be accepted by the API back-end application associated with the back-end API app registration.
  • appid (or azp): refers to the client app registation.
  • roles: refers to the configured roles for the client app registration in the context of the requested scope.

What is next

By obtaining and decoding an access token, we demonstrated that both the client and back-end app registrations work in conjunction with each other. The token was obtained through a shared secret; client credentials flow.

In the next step we will create the client web application that uses its managed identity to obtain an access token for the API omitting the need for secrets.