Skip to content

[Feature Request] Bearer tokens with Bound credentials #5791

@bgavrilMS

Description

@bgavrilMS

Problem statement

Motivation

Today, the SDK uses Bearer credentials to request Bearer tokens. These take the form of client assertions (JWTs created by the app and signed with a certificate) or federated credentials (JWTs issued by STS). To increase security posture, we propose to use bound credentials (i.e. mTLS bound) even when requesting Bearer tokens. This prevents attackers from stealing the client assertions, because Bearer assertions are either not created at all, or will be blocked by policy.

Note: When requesting bound (mtls-pop) tokens, bound credentials are mandatory.

Summary

Credential Proposal
Secret N/A
X509 Certificate The SDK acquires token from Entra mTLS endpoint, using the X509 certificate for mTLS. In most cases, a client assertion isn't created.
Federated Credential Acquire an MTLS-POP credential-token (i.e. JWT + X509) from the token issuer (e.g. MSI), and use that to acquire a Bearer token from Entra over mTLS with the X509

What auth flows are covered ?

For start, only client_credentials is covered and ESTS does not support this on all clouds. This is an EntraID only feature. In time, all confidential client flows will move to use mTLS.

Client Certificates

DevEx

var cca = ConfidentialClientApplicationBuilder
                    .Create(clientID)                    
+                    .WithCertificate(x509Certificate, new CertificateOptions() { UseMtls = false; })  // opt-in or opt-out
                    .Build();

var result = await cca.AcquireTokenForClient("scope")  
                                  .ExecuteAsync();

HttpClient

In case the Http transport is used, there are 2 interfaces exposed today:

  • IMsalHttpClientFactory
  • IMsalMtlsHttpClientFactory

We propose the following change: If the app developer or higher SDK implements IMsalHttpClientFactory but not IMsalMtlsHttpClientFactory, then MSAL will ignore IMsalHttpClientFactory and use its own HttpClient implemenatation to call over HTTP

ESTS support

Today, ESTS supports S2S flow without client_assertion on the wire, but all the other grants need to still have the client_assertion on the wire, while contacting the STS.

Eventually, the client_assertion should not be needed at all, but ESTS is not there yet.

Federated Credentials (FIC)

In case of FIC, the application must obtain a BOUND credential (i.e. JWT + certificate) from the federation provider (e.g. MSI or other token issuer). They can then provide them both to MSAL. So it is an explicit gesture at MSAL level, but higher level APIs can attempt do it automatically or as an opt-in.

var cca = ConfidentialClientApplicationBuilder
                    .Create(clientID)
+                    .WithClientAssertion((_) => (jwt, x509Certificate))   // not exact API
                    .Build();

var result = await cca.AcquireTokenForClient("scope")  
                                  .ExecuteAsync();

Higher level APIs (Azure SDK does not have higher level API for FIC) as per docs, can expose an option or attempt to get POP credentials whenever possible. This is safer because MTLS POP credential availability is sparse - only Windows CVM/TVM support it today. For example in Identity.Web this can be:

{
       "AzureAd": {
         "Instance": "https://login.microsoftonline.com/",
         "TenantId": "your-tenant-id",
         "ClientId": "your-client-id",
         "ClientCredentials": [
           {
             "SourceType": "SignedAssertionFromManagedIdentity",
             "ManagedIdentityClientId": "your-user-assigned-managed-identity-client-id"
             "TokenExchangeUrl": "api://AzureADTokenExchange" 
+           "UseBoundCredential": true
           }
         ]
       }
     }

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions