My bearer token is sts.windows.net, but I need it to be login.microsoftonline.com

I’m busy locking down my web applications in Azure and using my learnings on the day job. One way to do this is by making sure all requests are authenticated, and roles are granted accordingly.

Using the correct issuer

While checking out the token, I found the issuer (iss) contains the following value https://sts.windows.net/[tenantid]/.

{
  "aud": "f4c42c68-c881-4320-815c-1ca4f32cb6c5",
  "iss": "https://sts.windows.net/[tenantid]/",
  "iat": 1605812881,
  // all other properties of your token
}

The issuer is valid, but not the one I was expecting. When navigating to the metadata endpoint of your tenant (https://login.microsoftonline.com/[tenantid]/v2.0/.well-known/openid-configuration), you will see the issuer should be "issuer":"https://login.microsoftonline.com/[tenantid]/v2.0".

After doing a couple of minutes of research on the matter, it looks like the sts-endpoint is the Azure Active Directory v1 issuer. To make your App Registration work with the AAD v2 endpoints, you need to make a small change.

Changing the manifest

If you’ve read my other post, you’re probably already aware of the Manifest blade. This blade enables us to make changes to the App Registration, which don’t get exposed via the UI (yet). Changing your application to use the v2 endpoints is one of these changes. At the top of the file, there is an option called accessTokenAcceptedVersion. By default, this value is null.

{
	"id": "e68b291a-607e-4780-8a1e-0e9842dd3fde",
	"acceptMappedClaims": null,
	"accessTokenAcceptedVersion": null,
	"addIns": [],
	"allowPublicClient": null,
	"appId": "f4c42c68-c881-4320-815c-1ca4f32cb6c5",
	"appRoles": [
    ]
}

The documentation states the following:

Possible values for accesstokenAcceptedVersion are 1, 2, or null. If the value is null, this parameter defaults to 1, which corresponds to the v1.0 endpoint.

While I get the fallback of null is 1, it would make more sense (for me at least) to default this value at 2 for new App Registrations. This isn’t the default behavior; setting the accessTokenAcceptedVersion value is the only option. Don’t forget to save the manifest after changing this "accessTokenAcceptedVersion": 2.
Do note; it might take some time for this change to take effect, so don’t be afraid if the issuer isn’t updated in your tokens immediately. After a while, the correct issuer is shown in the token

{
  "aud": "f4c42c68-c881-4320-815c-1ca4f32cb6c5",
  "iss": "https://login.microsoftonline.com/[tenantid]/v2.0",
  "iat": 1605856255,
   // all other properties of your token

Changing via the Azure CLI

You can also make the above change by using the Azure CLI & the Graph API. There isn’t an easy command for you to use, so making a PATCH request is the only option available at the moment.

az rest `
    --method PATCH `
    --headers "Content-Type=application/json" `
    --uri https://graph.microsoft.com/v1.0/applications/f4c42c68-c881-4320-815c-1ca4f32cb6c5/ `
    --body '{"api":{"requestedAccessTokenVersion": 2}}'

Can’t I add the sts.windows.net to my Valid Issuers?

Well, yes, you can certainly do this.
You know the token originates from Azure Active Directory, and all information in it is valid.

However, this also means you will end doing something like the following:

services.AddAuthentication(options =>
    {
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        options.Authority = "someAuthority";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidAudience = "someAudience",
            ValidIssuer = $"https://sts.windows.net/{authSettings.TenantId:D}/"
        };
    });

Over here, you fill out the issuer by convention.

It works, but it is better to use the metadata endpoint to retrieve your tenant’s data.
The following piece of code to retrieve the Open ID configuration from your tenant and uses it in the TokenValidationParameters

var aadMetadataAddress = $"https://login.microsoft.com/{settings.TenantId:D}/v2.0/.well-known/openid-configuration";
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(aadMetadataAddress, new OpenIdConnectConfigurationRetriever());
var openIdConnectConfiguration = await configurationManager.GetConfigurationAsync();
return new TokenValidationParameters
{
    ValidAudience = settings.AppId.ToString("D"),
    IssuerSigningKeys = openIdConnectConfiguration.SigningKeys,
    ValidIssuer = openIdConnectConfiguration.Issuer
};

Using this code, you don’t have to create your own ValidIssuer, but can use the one specified in your tenant configuration. It will make your code a bit more robust, in my opinion.
As you can see in this sample, I’m also using the SigningKeys from the configuration to validate the token.


Share

comments powered by Disqus