Share via

Federated Credentials for Defender API

Jesper Vest Hansen 0 Reputation points
2025-11-27T09:52:54+00:00

Hello,

I am facing an issue with Workload Identity Federation.

I have a function app that is using App Registration secrets for getting an Access Token on the Defender For Cloud Endpoint (https://api.securitycenter.microsoft.com/.default).
And that works fine, but i want to avoid using secrets and therefore using Federated credentials by integration the Function App Identity as a Federated Credential on the App Registration.

But it is not working, I have tried a bunch of different things, and I can't find a lot of documentation on it, which is the reason I am posting a question here.

The code I have in my Function App to get an Access Token for Defender for Cloud Endpoint looks like this.

$remoteTenantId = "$($azure_tenant.TenantId)"

# Get token for multi-tenant app registration home tenant
if ($env:MSI_SECRET) {
	$resourceUri = 'api://AzureADTokenExchange'
	$tokenUri = '{0}?resource={1}&api-version=2019-08-01' -f $env:MSI_ENDPOINT, $resourceUri
	$tokenHeader = @{ "X-IDENTITY-HEADER" = $env:MSI_SECRET }
	$msiTokenRequest = Invoke-RestMethod -Method Get -Uri $tokenUri -Headers $tokenHeader
}


Write-Host "Home tenant token"
$msiTokenRequest.access_token

# Get token for remote tenant
$clientTokenBody = @{
	grant_type            = 'client_credentials'
	client_id             = $app_registration_client_id
	client_assertion      = $msiTokenRequest.access_token
	client_assertion_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
	scope                 = 'https://api.security.microsoft.com/.default'
}
$clientAuthUri = "https://login.microsoftonline.com/$($remoteTenantId)/oauth2/v2.0/token"
$clientAuthRequest = Invoke-RestMethod -Method Post -Uri $clientAuthUri -Form $clientTokenBody

Gettting the Access Token from home tenant works fine, but when i try to get Access Token for remote tenant and for the Defender for Cloud endpoint(https://api.securitycenter.microsoft.com/.default) it does not work. I am getting the following error:

ERROR: Response status code does not indicate success: 400 (Bad Request). Exception : Type : Microsoft.PowerShell.Commands.HttpResponseException Response : StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: { Cache-Control: no-store, no-cache Pragma: no-cache Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" x-ms-request-id: 12c789e9-fe51-4783-b37b-ad9ea85aac00 x-ms-ests-server: 2.1.22549.4 - NEULR1 ProdSlices x-ms-srs: 1.P Content-Security-Policy-Report-Only: object-src 'none'; base-uri 'self'; script-src 'self' 'nonce-d-1Eox88qrQ3hbylAXSxZg' 'unsafe-inline' 'unsafe-eval' https://.msauth.net https://.msftauth.net https://.msftauthimages.net https://.msauthimages.net https://.msidentity.com https://.microsoftonline-p.com https://.microsoftazuread-sso.com https://.azureedge.net https://.outlook.com https://.office.com https://.office365.com https://.microsoft.com https://*.bing.com 'report-sample'; report-uri https://csp.microsoft.com/report/ESTS-UX-All X-XSS-Protection: 0 Set-Cookie: fpc=Aq_e_9uFxHJHrkCLfjEqUHA; expires=Sat, 27-Dec-2025 09:42:39 GMT; path=/; secure; HttpOnly; SameSite=None Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; samesite=none; httponly Set-Cookie: stsservicecookie=estsfd; path=/; secure; samesite=none; httponly Date: Thu, 27 Nov 2025 09:42:39 GMT Content-Type: application/json; charset=utf-8 Expires: -1 Content-Length: 391 } StatusCode : BadRequest TargetSite : Name : ThrowTerminatingError DeclaringType : [System.Management.Automation.MshCommandRuntime] MemberType : Method Module : System.Management.Automation.dll Message : Response status code does not indicate success: 400 (Bad Request). Source : System.Management.Automation HResult : -2146233088 StackTrace : at System.Management.Automation.MshCommandRuntime.ThrowTerminatingError(ErrorRecord errorRecord) TargetObject : Method: POST, RequestUri: 'https://login.microsoftonline.com/1255969d-7315-4f57-b47f-c922043f1e5d/oauth2/v2.0/token', Version: 1.1, Content: System.Net.Http.MultipartFormDataContent, Headers: { User-Agent: Mozilla/5.0 User-Agent: (Windows NT 10.0; Microsoft Windows 10.0.20348; en-US) User-Agent: PowerShell/7.4.12 Accept-Encoding: gzip Accept-Encoding: deflate Accept-Encoding: br Content-Type: multipart/form-data; boundary="72845d2c-460d-4627-afcb-d4de9d063847" Content-Length: 2586 } CategoryInfo : InvalidOperation: (Method: POST, Reque…ent-Length: 2586 }:HttpRequestMessage) [Invoke-RestMethod], HttpResponseException FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand ErrorDetails : { "error": "invalid_request", "error_description": "AADSTS90023: Unexpected client assertion type. Trace ID: 12c789e9-fe51-4783-b37b-ad9ea85aac00 Correlation ID: 60388e5f-8cf9-4558-8368-2af2079e0b98 Timestamp: 2025-11-27 09:42:39Z", "error_codes": [ 90023 ], "timestamp": "2025-11-27 09:42:39Z", "trace_id": "12c789e9-fe51-4783-b37b-ad9ea85aac00", "correlation_id": "60388e5f-8cf9-4558-8368-2af2079e0b98" } InvocationInfo : MyCommand : Invoke-RestMethod ScriptLineNumber : 303 OffsetInLine : 30 HistoryId : 1 ScriptName : C:\home\site\wwwroot\defenderCollectorGetDiscoveredVulnerabilites\run.ps1 Line : $clientAuthRequest = Invoke-RestMethod -Method Post -Uri $clientAuthUri -Form $clientTokenBody Statement : Invoke-RestMethod -Method Post -Uri $clientAuthUri -Form $clientTokenBody PositionMessage : At C:\home\site\wwwroot\defenderCollectorGetDiscoveredVulnerabilites\run.ps1:303 char:30 + … thRequest = Invoke-RestMethod -Method Post -Uri $clientAuthUri -Form … + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PSScriptRoot : C:\home\site\wwwroot\defenderCollectorGetDiscoveredVulnerabilites PSCommandPath : C:\home\site\wwwroot\defenderCollectorGetDiscoveredVulnerabilites\run.ps1 InvocationName : Invoke-RestMethod CommandOrigin : Internal ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\defenderCollectorGetDiscoveredVulnerabilites\run.ps1: line 303

Extra details:

  • It is a multi-tenant App Registration, and it works fine with App Registration secret.
  • Function App systems assigned managed identity has been integrated as a federated credential on the App Registration
  • The App Registration has been enrolled into an external Azure Tenant, and API permissions have also been granted Administrator access.
  • I have tried a bunch of different URI's in the scope and lots of other things, but nothing is working without secrets.

Am i doing something wrong or is it simply not a capability Workload Identity Federation has ?

best regards

Jesper

Azure Functions
Azure Functions

An Azure service that provides an event-driven serverless compute platform.


1 answer

Sort by: Most helpful
  1. Sina Salam 28,281 Reputation points Volunteer Moderator
    2026-03-29T13:41:54.1733333+00:00

    Hello Jesper Vest Hansen,

    Welcome to the Microsoft Q&A and thank you for posting your questions here.

    I understand that you are having federated Credentials for Defender API issue.

    Because, the cross‑tenant “workload identity federation” using a Managed Identity fails unless the target app is explicitly trusted and provisioned in that tenant, and the FIC uses the exact audience api://AzureADTokenExchange; otherwise the remote tenant won’t accept the token (multi‑tenant trust is not implicit) (see FIC overview and Configure an app to trust a managed identity prerequisites/restrictions (same‑tenant or multi‑tenant + provisioning). - https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-1.0

    The symptom (unsupported flow) shows that ManagedIdentity > token exchange > remote tenant ⇒ 401/invalid_token.

    To resolve this, follow the below steps:

    1. Use the supported app‑only pattern (most recommended): Register an app, grant Defender API Application permissions, and authenticate with client secret or certificate; then request a token for https://api.security.microsoft.com/.default and call the Defender API (official MDE/XDR guides). - https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity, https://learn.microsoft.com/en-us/defender-endpoint/api/exposed-apis-create-app-webapp
         # OAuth2 v2.0 (client credentials)
         curl -s -X POST https://login.microsoftonline.com/&lt;tenant&gt;/oauth2/v2.0/token </span>
          -d 'grant_type=client_credentials&client_id=<appId>&client_secret=<secret>'</span>
          -d 'scope=https://api.security.microsoft.com/.default'
      
    2. Make it multi‑tenant and consent in the customer tenant by setting the app to multi‑tenant, then have an admin in the remote tenant grant consent to the requested app roles (tenant‑wide admin consent flow). - https://learn.microsoft.com/en-us/defender-xdr/api-create-app-web, https://learn.microsoft.com/en-us/defender-xdr/api-create-app-web
         # Admin consent URL the customer executes
         https://login.microsoftonline.com/&lt;remoteTenant&gt;/adminconsent?client_id=&lt;appId>
      
    3. Only if you MUST use Federation keep it single‑tenant (same tenant for MI and app) and configure the FIC precisely with issuer/subject matching your Managed Identity and audience set to api://AzureADTokenExchange (case‑sensitive). - https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-1.0, https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/grant-admin-consent
    4.    { "issuer":"https://login.microsoftonline.com/&lt;tenant&gt;/v2.0",
           "subject":"<managed-identity-object-id>",
           "audiences":["api://AzureADTokenExchange"] 
         }
      
    5. Then, use the app’s token to call Defender XDR or Defender for Endpoint APIs over api.security.microsoft.com (or geo‑specific hosts) as documented. - https://learn.microsoft.com/en-us/defender-endpoint/api/exposed-apis-create-app-webapp, https://learn.microsoft.com/en-us/defender-endpoint/api/exposed-apis-create-app-nativeapp
         curl -H "Authorization: Bearer $ACCESS_TOKEN" </span>
           https://api.security.microsoft.com/api/incidents
      
    6. For cross‑tenant Defender API access, prefer certificate‑based client‑credential over secrets, and avoid MI‑based federation for this scenario; Microsoft explicitly recommends certificates for production app credentials. - https://learn.microsoft.com/en-us/defender-endpoint/api/exposed-apis-create-app-webapp, https://learn.microsoft.com/en-us/entra/identity-platform/how-to-add-credentials
         # Upload cert to the app, then authenticate with client assertion (JWT)
         # (per Entra “Add and manage application credentials” guidance)
      

    I hope this is helpful! Do not hesitate to let me know if you have any other questions or clarifications.


    Please don't forget to close up the thread here by upvoting and accept it as an answer if it is helpful.

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.