While I consider it crucial to use Certificate Credentials for Client_Credential based flows (Application authentication, without any user context), I have always regarded it as optional to use a certificate for delegated flows with Confidental OAuth2 clients. The reason for this is that the otherwise not so strong method of password-based client_secret cannot be used alone in user flows; it merely serves as proof that the back-end client is in possession of the client secret.

I have also consistently advised against pairing App and delegated permissions under a single client, as it would render the password client secret alone usable for app flows. Although I would not recommend pairing delegated and app permissions for either certificate-based flows, that being the certificate is still much less likely to leak, as it is never directly part of the request; only a signed assertion is generated from the private key. Taking it to the extreme, you can also protect this private key with TPM if you have a web application that supports requesting signing operations from TPM.
Implementation
So how do we provide this signed assertion in delegated Entra ID flows, such as authorization code flow? Well, MS has it all documented, so my role is only to show snippets of technical example below
Let’s use some previous work, to make the this happen
- Request authorization code
https://login.microsoftonline.com/457a8f99-4a48-40b1-88f8-2a9b0515b5a9/oauth2/v2.0/authorize
?client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_id=32f87519-31db-4e41-bd88-001bd8e44ffa
&response_type=code
&response_mode=form_post
&state=12345
&nonce=abcde
&redirect_uri=https://yourapp.com/callback
&scope=openid
- You can send the authorization code to an destination, that does not respond, this makes it convenient for just copying the unused code from the browser

- Send the authorization code from back-end to Entra ID to obtain Access Token. The only differences are that in place of client_secret based flow is that you have now
client_assertion(containing identical signed token to client certificate based flows) and client_assertion_type with value ofurn:ietf:params:oauth:client-assertion-type:jwt-bearer
The token sent in the assertion field is as follows (note, this is not the user token); it is a substitution for the client secret, but instead contains the signed assertion as shown in the image below.


- Compared to normal token, the response token will include value of 2 for appidacr, which I’ve written about in another blog Azure API management – Enforce use of Certificate in Client Credentials Flow

Ending words:
This is highly useful way avoiding use of passwords in Entra ID Apps, while it is not as critical as it would be in app based flows, it still provides similar benefits in client_credential based flows

0 comments on “Using certificate credential for delegated Oauth2 flows in Entra ID”