Using encrypted access tokens in Azure with Microsoft.Identity.Web and Azure App registrations

This post shows how to use encrypted access tokens with Azure AD App registrations using Microsoft.Identity.Web. By using encrypted access tokens, only applications with access to the private key can decrypt the tokens. When using encrypted tokens, you can prevent access tokens data being used or read by such tools as https://jwt.ms or https://jwt.io and prevent the payload claims being read.

Code: https://github.com/damienbod/AzureADAuthRazorUiServiceApiCertificate

Posts in this series

Setup

Two applications were created to demonstrate the AAD token encryption. An ASP.NET Core application was created which implements an API using Microsoft.Identity.Web to secure the API. The API uses an encrypted token. Secondly, a UI app was created to login to AAD and request the API using the API access_as_user scope. The decryption, encryption certificate was created in Azure Key Vault and the public key .cer file was downloaded. This public key is used in the Azure App Registration for the token encryption.

Setting up the Azure App Registration

The Azure App registration for the Web API is setup to use token encyption. The token which was created in Azure Key Vault can be added to the keyCredentials array in the App Azure Registration manifest file. The customKeyIdentifier is the thumbprint and the usage is set to Encrypt. The value property contains the base64 .cer file which was download from your Key Vault.

"keyCredentials": [
	{
		"customKeyIdentifier": "E1454F331F3DBF52523AAF0913DB521849E05AD3",
		"endDate": "2021-10-20T12:19:52Z",
		"keyId": "53095330-1680-4a8d-bf0d-8d0d042fe88b",
		"startDate": "2020-10-20T12:09:52Z",
		"type": "AsymmetricX509Cert",
		"usage": "Encrypt",
		"value": "--your base 64 .cer , ie public key --",
		"displayName": "CN=myTokenEncyptionCert"
	},

],

The tokenEncryptionKeyId property in the Azure App Registration manifest is used to define the certificate which will be used for token encryption. This is set to the keyId of the certificate definition in the keyCredentials array.

"tokenEncryptionKeyId": "53095330-1680-4a8d-bf0d-8d0d042fe88b"

Note: If you upload the certificate to the Azure App registration using the portal, the usage will be set to verify and it cannot be used for token encryption.

Configuration of API application

The ASP.NET Core application uses AddMicrosoftIdentityWebApiAuthentication with the default AzureAD configuration. This authorizes the API requests.

public void ConfigureServices(IServiceCollection services)
{
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            IdentityModelEventSource.ShowPII = true;

            services.AddMicrosoftIdentityWebApiAuthentication(Configuration);

            services.AddControllers(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                   // .RequireClaim("email") // disabled this to test with users that have no email (no license added)
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            });
}

The app.settings defines the TokenDecryptionCertificates to use the Key Vault Certificate which is used for the token decryption. This is the same certificate which was used in the Azure App Registration. We used the public key from the certificate in the manifest definition.

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "damienbodhotmail.onmicrosoft.com",
    "TenantId": "7ff95b15-dc21-4ba6-bc92-824856578fc1",
    "ClientId": "fdc48df2-2b54-411b-a684-7d9868ce1a95",
    "TokenDecryptionCertificates": [
      {
        "SourceType": "KeyVault",
        "KeyVaultUrl": "https://damienbod.vault.azure.net",
        "KeyVaultCertificateName": "DecryptionCertificateCert2"
      }
    ]
  },

Configuration of UI application which calls API

The UI application which logins in, gives consent does not require the TokenDecryptionCertificates to use the API. It just uses a ClientCertificates to verify itself. This is not the same certicate and will have a verify usage in the Azure AD App Registration manifest.

"AzureAd": {
	"Instance": "https://login.microsoftonline.com/",
	"Domain": "damienbodhotmail.onmicrosoft.com",
	"TenantId": "7ff95b15-dc21-4ba6-bc92-824856578fc1",
	"ClientId": "8e2b45c2-cad0-43c3-8af2-b32b73de30e4",
	"CallbackPath": "/signin-oidc",
	"SignedOutCallbackPath ": "/signout-callback-oidc",
	"ClientCertificates": [
	  {
		"SourceType": "KeyVault",
		"KeyVaultUrl": "https://damienbod.vault.azure.net",
		"KeyVaultCertificateName": "DcPortalCert"
	  }
	]
},
"CallApi": {
	"ScopeForAccessToken": "api://fdc48df2-2b54-411b-a684-7d9868ce1a95/access_as_user",
	"ApiBaseAddress": "https://localhost:44390"
},

If you start the applications without the App registration token encryption you can debug the application and view the token claims as the default produces a JWT access token.

When using token encryption, the payload can no longer be viewed.

Links

https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/howto-saml-token-encryption

Authentication and the Azure SDK

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#second-case-access-token-request-with-a-certificate

https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Client-credential-flows

https://tools.ietf.org/html/rfc7523

https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens

https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Client-Assertions

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

https://github.com/AzureAD/microsoft-identity-web/wiki/Using-certificates#describing-client-certificates-to-use-by-configuration

API Security with OAuth2 and OpenID Connect in Depth with Kevin Dockx, August 2020

https://www.scottbrady91.com/OAuth/Removing-Shared-Secrets-for-OAuth-Client-Authentication

https://github.com/KevinDockx/ApiSecurityInDepth

https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki

One comment

  1. […] Using encrypted access tokens in Azure with Microsoft.Identity.Web and Azure App registrations (Damien Bowden) […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: