{
  "schemaVersion": "1.0",
  "code": "7002121",
  "name": null,
  "title": "AADSTS7002121: Federated credential audience doesn't match the assertion (fix)",
  "url": "https://brambrinkmeier.com/entra/aadsts/7002121/",
  "alternates": {
    "markdown": "https://brambrinkmeier.com/entra/aadsts/7002121.md",
    "json": "https://brambrinkmeier.com/api/aadsts/7002121.json",
    "html": "https://brambrinkmeier.com/entra/aadsts/7002121/"
  },
  "description": "AADSTS7002121: the external token's audience matches no federated identity credential. Not in Microsoft's error list. Fix and KQL.",
  "summary": "AADSTS7002121 means a workload presented an external token whose aud claim matches no federated identity credential on the app or managed identity. Microsoft's error reference doesn't list it. Usually the token was requested for the wrong audience instead of api://AzureADTokenExchange, or the case differs. It is a configuration error with low attack value.",
  "inMicrosoftReference": false,
  "unlistedChecked": "2026-10-30",
  "meaningText": "Microsoft's [error code reference](https://learn.microsoft.com/entra/identity-platform/reference-error-codes) doesn't list AADSTS7002121 (checked 30 October 2026). We found no other Microsoft page that names it either. The wording below is from a lab run, not from a Microsoft page.\n\nA federated identity credential on an app registration or a user-assigned managed identity says which external token Entra will exchange for an access token. It pins three values: issuer, subject and audience. 7002121 is the audience failing to match.\n\nMicrosoft's Graph overview describes the property: **audiences** is *\"the audience that can appear in the external token\"*, it *\"says what Microsoft identity platform should accept in the `aud` claim in the incoming token\"*, and it *\"should be set to `api://AzureADTokenExchange` for Microsoft Entra ID\"*. The restrictions page adds *\"You must add a single audience value, which has a limit of 600 characters\"*, and lists the error a wrong count gives at configuration time: *\"Federated identity credentials must have exactly one audience.\"*\n\nThe accepted value depends on the cloud. For a managed identity acting as the credential, Microsoft lists:\n\n| Cloud | Audience value |\n|---|---|\n| Microsoft Entra ID global service | `api://AzureADTokenExchange` |\n| Microsoft Entra ID for US Government | `api://AzureADTokenExchangeUSGov` |\n| Microsoft Entra China operated by 21Vianet | `api://AzureADTokenExchangeChina` |\n\nMatching is case-sensitive. Microsoft's breaking-changes page, under *\"Federated Identity Credentials now use case-sensitive matching\"* with an effective date of September 2024: *\"Previously, when matching the Federated Identity Credential (FIC) `issuer`, `subject`, and `audience` values against the corresponding `issuer`, `subject`, and `audience` values contained in the token sent to Microsoft Entra ID by an external IdP, case-insensitive matching was used. To provide more fine-grained control to customers, we're switching to enforcing case-sensitive matching.\"*\n\nThe siblings tell you which of the three values failed:\n\n- [700211](https://brambrinkmeier.com/entra/aadsts/700211/) issuer doesn't match\n- [700213](https://brambrinkmeier.com/entra/aadsts/700213/) subject doesn't match\n- [7002138](https://brambrinkmeier.com/entra/aadsts/7002138/) subject matches except for case\n- [700212](https://brambrinkmeier.com/entra/aadsts/700212/) audience doesn't match, in user reports\n- [70025](https://brambrinkmeier.com/entra/aadsts/70025/) the app has no federated credentials at all\n\n[700212](https://brambrinkmeier.com/entra/aadsts/700212/) carries almost the same message text and the same meaning. Users report 700212; our lab tenant returned 7002121 for the audience case on 30 October 2026. We can't tell from one tenant whether 700212 is older, cloud-specific or issuer-specific, so treat the two as one condition and match on both in detections.",
  "sections": [
    {
      "heading": "What does AADSTS7002121 mean?",
      "text": "Microsoft's [error code reference](https://learn.microsoft.com/entra/identity-platform/reference-error-codes) doesn't list AADSTS7002121 (checked 30 October 2026). We found no other Microsoft page that names it either. The wording below is from a lab run, not from a Microsoft page.\n\nA federated identity credential on an app registration or a user-assigned managed identity says which external token Entra will exchange for an access token. It pins three values: issuer, subject and audience. 7002121 is the audience failing to match.\n\nMicrosoft's Graph overview describes the property: **audiences** is *\"the audience that can appear in the external token\"*, it *\"says what Microsoft identity platform should accept in the `aud` claim in the incoming token\"*, and it *\"should be set to `api://AzureADTokenExchange` for Microsoft Entra ID\"*. The restrictions page adds *\"You must add a single audience value, which has a limit of 600 characters\"*, and lists the error a wrong count gives at configuration time: *\"Federated identity credentials must have exactly one audience.\"*\n\nThe accepted value depends on the cloud. For a managed identity acting as the credential, Microsoft lists:\n\n| Cloud | Audience value |\n|---|---|\n| Microsoft Entra ID global service | `api://AzureADTokenExchange` |\n| Microsoft Entra ID for US Government | `api://AzureADTokenExchangeUSGov` |\n| Microsoft Entra China operated by 21Vianet | `api://AzureADTokenExchangeChina` |\n\nMatching is case-sensitive. Microsoft's breaking-changes page, under *\"Federated Identity Credentials now use case-sensitive matching\"* with an effective date of September 2024: *\"Previously, when matching the Federated Identity Credential (FIC) `issuer`, `subject`, and `audience` values against the corresponding `issuer`, `subject`, and `audience` values contained in the token sent to Microsoft Entra ID by an external IdP, case-insensitive matching was used. To provide more fine-grained control to customers, we're switching to enforcing case-sensitive matching.\"*\n\nThe siblings tell you which of the three values failed:\n\n- [700211](https://brambrinkmeier.com/entra/aadsts/700211/) issuer doesn't match\n- [700213](https://brambrinkmeier.com/entra/aadsts/700213/) subject doesn't match\n- [7002138](https://brambrinkmeier.com/entra/aadsts/7002138/) subject matches except for case\n- [700212](https://brambrinkmeier.com/entra/aadsts/700212/) audience doesn't match, in user reports\n- [70025](https://brambrinkmeier.com/entra/aadsts/70025/) the app has no federated credentials at all\n\n[700212](https://brambrinkmeier.com/entra/aadsts/700212/) carries almost the same message text and the same meaning. Users report 700212; our lab tenant returned 7002121 for the audience case on 30 October 2026. We can't tell from one tenant whether 700212 is older, cloud-specific or issuer-specific, so treat the two as one condition and match on both in detections."
    },
    {
      "heading": "Reproduced in the lab",
      "text": "On 30 October 2026 an automated lab run created an app registration with a federated identity credential, then presented a token whose `aud` claim was a GUID rather than the credential's configured audience. Entra returned `AADSTS7002121`:\n\n> AADSTS7002121: No matching federated identity record found for presented assertion audience '\\<audience>'. The Audience for the federat...\n\nThe lab records only the first line of `error_description`, cut at about 160 characters, so the sentence about the configured audience is truncated. The same run confirmed the siblings on the same app: a wrong issuer gave [700211](https://brambrinkmeier.com/entra/aadsts/700211/), a wrong subject gave [700213](https://brambrinkmeier.com/entra/aadsts/700213/), a subject differing only in case gave [7002138](https://brambrinkmeier.com/entra/aadsts/7002138/), and an app with no credential at all gave [70025](https://brambrinkmeier.com/entra/aadsts/70025/). So Entra does distinguish the three fields, and 7002121 is specifically the audience.\n\nNo sign-in log row was captured. See [how pages are checked](https://brambrinkmeier.com/methodology/)."
    },
    {
      "heading": "Is it an attack?",
      "text": "No. The workload asked its own identity provider for a token meant for something else, or the credential and the workload disagree about the audience string.\n\n| Pattern | Likely meaning |\n|---|---|\n| A new pipeline or workload fails on its first federated run | The token is requested for the provider's default audience rather than `api://AzureADTokenExchange`. |\n| Kubernetes pod fails and the audience in the error is a cluster URL | The pod is using its default service account token, not one projected for the credential's audience. |\n| Works in the commercial cloud, fails in US Government or China | The audience must be that cloud's value from the table above. |\n| Only the case differs | Matching has been case-sensitive since the September 2024 change. Fix the case on whichever side is wrong. |\n| The error appears right after someone edited the credential | The audience was changed on one side only. A credential holds exactly one audience value. |"
    },
    {
      "heading": "How do I find it in my logs (KQL)?",
      "text": "Which sign-in table 7002121 lands in is undocumented. Our reading: an app registration's token request lands in `AADServicePrincipalSignInLogs`, and a user-assigned managed identity presenting the token may land in the managed identity sign-in log instead. Start with a union so you don't miss it:\n\n```kusto\nunion withsource=SourceTable\n    SigninLogs,\n    AADNonInteractiveUserSignInLogs,\n    AADServicePrincipalSignInLogs,\n    AADManagedIdentitySignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType in (\"7002121\", \"700212\") or ResultSignature in (\"7002121\", \"700212\")\n| summarize Rows = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceTable, ResultType\n```\n\nThe query filters `ResultSignature` as well as `ResultType` because the two tables document the column differently. For `SigninLogs`, `ResultType` *\"provides the 5-6 digit error code that's generated during a sign-in event\"*; for `AADServicePrincipalSignInLogs` it is described only as *\"Success or Failure\"*, with `ResultSignature` holding *\"the error code, if any, for the sign-in operation\"*. Look at one failed row in your own workspace and keep the filter that matches.\n\nWhich app and which credential, with the error text:\n\n```kusto\nAADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType in (\"7002121\", \"700212\") or ResultSignature in (\"7002121\", \"700212\")\n| summarize Failures = count(),\n            FirstSeen = min(TimeGenerated),\n            LastSeen = max(TimeGenerated),\n            Credentials = make_set(FederatedCredentialId, 5),\n            CredentialTypes = make_set(ClientCredentialType, 5),\n            Descriptions = make_set(ResultDescription, 5),\n            IPs = make_set(IPAddress, 10)\n          by AppId, ServicePrincipalName\n| sort by Failures desc\n```\n\n`FederatedCredentialId` is documented as *\"Th identifier of an application's federated identity credential if a federated identity credential was used to sign in\"* (the typo is Microsoft's), and `ClientCredentialType` as *\"the type of client credential used\"*. Whether either column is filled in when the match fails is not documented; check a row before building a rule on it. The same goes for whether `ResultDescription` carries the presented audience.\n\nA failing workload that also succeeds tells you the audience it should be sending. Compare the two:\n\n```kusto\nAADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where AppId == \"<app id of the failing app>\"\n| summarize Rows = count(), LastSeen = max(TimeGenerated)\n          by ResultType, ResultSignature, FederatedCredentialId, ClientCredentialType\n| sort by LastSeen desc\n```\n\nA starting point for alerting: more than about 20 of these in an hour for one app usually means a deployment went out with the wrong audience, not an attack."
    },
    {
      "heading": "How do I fix AADSTS7002121?",
      "text": "**For developers and pipeline owners:**\n1. Read the audience out of the error message, or decode the token your workload presents and read its `aud` claim.\n2. Request the token for `api://AzureADTokenExchange`, in that exact case, unless your credential deliberately uses another value. Use the cloud-specific value from the table above outside the commercial cloud.\n3. Kubernetes: mount a projected service account token with that audience instead of the pod's default token.\n4. GitHub Actions and Azure DevOps: leave the audience input of the login step at its default unless the credential says otherwise.\n5. If the issuer or the subject is also wrong, you will see [700211](https://brambrinkmeier.com/entra/aadsts/700211/) or [700213](https://brambrinkmeier.com/entra/aadsts/700213/) next. Fix all three against the values in the error messages.\n\n**For admins:**\n1. Open the app registration or managed identity, **Certificates & secrets** > **Federated credentials**, and read the audience. It holds exactly one value.\n2. If you changed it from `api://AzureADTokenExchange`, every workload using that credential must request the same string, in the same case.\n3. Don't fix a case mismatch by recreating the credential with a different case. Fix whichever side is wrong and leave the other alone, so the other workloads using it keep working."
    }
  ],
  "microsoftWording": null,
  "securityReading": {
    "category": {
      "id": "app-config",
      "label": "App configuration"
    },
    "kind": {
      "id": "config",
      "label": "Configuration error"
    },
    "attackSignal": {
      "level": "low",
      "label": "Low: usually configuration or user error"
    },
    "mitre": [],
    "tables": [
      "AADServicePrincipalSignInLogs"
    ],
    "isItAnAttack": "No. The workload asked its own identity provider for a token meant for something else, or the credential and the workload disagree about the audience string.\n\n| Pattern | Likely meaning |\n|---|---|\n| A new pipeline or workload fails on its first federated run | The token is requested for the provider's default audience rather than `api://AzureADTokenExchange`. |\n| Kubernetes pod fails and the audience in the error is a cluster URL | The pod is using its default service account token, not one projected for the credential's audience. |\n| Works in the commercial cloud, fails in US Government or China | The audience must be that cloud's value from the table above. |\n| Only the case differs | Matching has been case-sensitive since the September 2024 change. Fix the case on whichever side is wrong. |\n| The error appears right after someone edited the credential | The audience was changed on one side only. A credential holds exactly one audience value. |",
    "conditionalAccess": null
  },
  "kql": [
    {
      "title": null,
      "leadIn": "Which sign-in table 7002121 lands in is undocumented. Our reading: an app registration's token request lands in `AADServicePrincipalSignInLogs`, and a user-assigned managed identity presenting the token may land in the managed identity sign-in log instead. Start with a union so you don't miss it:",
      "query": "union withsource=SourceTable\n    SigninLogs,\n    AADNonInteractiveUserSignInLogs,\n    AADServicePrincipalSignInLogs,\n    AADManagedIdentitySignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType in (\"7002121\", \"700212\") or ResultSignature in (\"7002121\", \"700212\")\n| summarize Rows = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceTable, ResultType"
    },
    {
      "title": null,
      "leadIn": "Which app and which credential, with the error text:",
      "query": "AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType in (\"7002121\", \"700212\") or ResultSignature in (\"7002121\", \"700212\")\n| summarize Failures = count(),\n            FirstSeen = min(TimeGenerated),\n            LastSeen = max(TimeGenerated),\n            Credentials = make_set(FederatedCredentialId, 5),\n            CredentialTypes = make_set(ClientCredentialType, 5),\n            Descriptions = make_set(ResultDescription, 5),\n            IPs = make_set(IPAddress, 10)\n          by AppId, ServicePrincipalName\n| sort by Failures desc"
    },
    {
      "title": null,
      "leadIn": "A failing workload that also succeeds tells you the audience it should be sending. Compare the two:",
      "query": "AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where AppId == \"<app id of the failing app>\"\n| summarize Rows = count(), LastSeen = max(TimeGenerated)\n          by ResultType, ResultSignature, FederatedCredentialId, ClientCredentialType\n| sort by LastSeen desc"
    }
  ],
  "kqlSectionText": "Which sign-in table 7002121 lands in is undocumented. Our reading: an app registration's token request lands in `AADServicePrincipalSignInLogs`, and a user-assigned managed identity presenting the token may land in the managed identity sign-in log instead. Start with a union so you don't miss it:\n\n```kusto\nunion withsource=SourceTable\n    SigninLogs,\n    AADNonInteractiveUserSignInLogs,\n    AADServicePrincipalSignInLogs,\n    AADManagedIdentitySignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType in (\"7002121\", \"700212\") or ResultSignature in (\"7002121\", \"700212\")\n| summarize Rows = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceTable, ResultType\n```\n\nThe query filters `ResultSignature` as well as `ResultType` because the two tables document the column differently. For `SigninLogs`, `ResultType` *\"provides the 5-6 digit error code that's generated during a sign-in event\"*; for `AADServicePrincipalSignInLogs` it is described only as *\"Success or Failure\"*, with `ResultSignature` holding *\"the error code, if any, for the sign-in operation\"*. Look at one failed row in your own workspace and keep the filter that matches.\n\nWhich app and which credential, with the error text:\n\n```kusto\nAADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType in (\"7002121\", \"700212\") or ResultSignature in (\"7002121\", \"700212\")\n| summarize Failures = count(),\n            FirstSeen = min(TimeGenerated),\n            LastSeen = max(TimeGenerated),\n            Credentials = make_set(FederatedCredentialId, 5),\n            CredentialTypes = make_set(ClientCredentialType, 5),\n            Descriptions = make_set(ResultDescription, 5),\n            IPs = make_set(IPAddress, 10)\n          by AppId, ServicePrincipalName\n| sort by Failures desc\n```\n\n`FederatedCredentialId` is documented as *\"Th identifier of an application's federated identity credential if a federated identity credential was used to sign in\"* (the typo is Microsoft's), and `ClientCredentialType` as *\"the type of client credential used\"*. Whether either column is filled in when the match fails is not documented; check a row before building a rule on it. The same goes for whether `ResultDescription` carries the presented audience.\n\nA failing workload that also succeeds tells you the audience it should be sending. Compare the two:\n\n```kusto\nAADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where AppId == \"<app id of the failing app>\"\n| summarize Rows = count(), LastSeen = max(TimeGenerated)\n          by ResultType, ResultSignature, FederatedCredentialId, ClientCredentialType\n| sort by LastSeen desc\n```\n\nA starting point for alerting: more than about 20 of these in an hour for one app usually means a deployment went out with the wrong audience, not an attack.",
  "fix": {
    "short": "Pipeline owner: read the audience from the error message or the token's `aud` claim, and request the token for `api://AzureADTokenExchange`, in that exact case. Admin: check the single audience value on the federated identity credential and make every workload that uses it ask for the same string.",
    "steps": "**For developers and pipeline owners:**\n1. Read the audience out of the error message, or decode the token your workload presents and read its `aud` claim.\n2. Request the token for `api://AzureADTokenExchange`, in that exact case, unless your credential deliberately uses another value. Use the cloud-specific value from the table above outside the commercial cloud.\n3. Kubernetes: mount a projected service account token with that audience instead of the pod's default token.\n4. GitHub Actions and Azure DevOps: leave the audience input of the login step at its default unless the credential says otherwise.\n5. If the issuer or the subject is also wrong, you will see [700211](https://brambrinkmeier.com/entra/aadsts/700211/) or [700213](https://brambrinkmeier.com/entra/aadsts/700213/) next. Fix all three against the values in the error messages.\n\n**For admins:**\n1. Open the app registration or managed identity, **Certificates & secrets** > **Federated credentials**, and read the audience. It holds exactly one value.\n2. If you changed it from `api://AzureADTokenExchange`, every workload using that credential must request the same string, in the same case.\n3. Don't fix a case mismatch by recreating the credential with a different case. Fix whichever side is wrong and leave the other alone, so the other workloads using it keep working."
  },
  "labReproduced": {
    "date": "2026-10-30",
    "method": "Client-credentials token request with a federated identity credential, against a lab tenant",
    "scenario": "Federated credential: audience does not match",
    "message": "AADSTS7002121: No matching federated identity record found for presented assertion audience '{audience-id}'. The Audience for the federat",
    "logCaptured": null,
    "kqlTested": null
  },
  "labSectionText": "On 30 October 2026 an automated lab run created an app registration with a federated identity credential, then presented a token whose `aud` claim was a GUID rather than the credential's configured audience. Entra returned `AADSTS7002121`:\n\n> AADSTS7002121: No matching federated identity record found for presented assertion audience '\\<audience>'. The Audience for the federat...\n\nThe lab records only the first line of `error_description`, cut at about 160 characters, so the sentence about the configured audience is truncated. The same run confirmed the siblings on the same app: a wrong issuer gave [700211](https://brambrinkmeier.com/entra/aadsts/700211/), a wrong subject gave [700213](https://brambrinkmeier.com/entra/aadsts/700213/), a subject differing only in case gave [7002138](https://brambrinkmeier.com/entra/aadsts/7002138/), and an app with no credential at all gave [70025](https://brambrinkmeier.com/entra/aadsts/70025/). So Entra does distinguish the three fields, and 7002121 is specifically the audience.\n\nNo sign-in log row was captured. See [how pages are checked](https://brambrinkmeier.com/methodology/).",
  "labRuns": [
    {
      "date": "2026-10-30",
      "run": "round 5",
      "method": "token-endpoint requests against a lab tenant, using lab-created test apps",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/69",
      "scenario": "Federated credential: audience does not match",
      "expected": "700212 / 700213 / 70021",
      "got": "7002121",
      "matchedExpectation": false,
      "message": "AADSTS7002121: No matching federated identity record found for presented assertion audience '{audience-id}'. The Audience for the federat"
    },
    {
      "date": "2026-10-30",
      "run": "round 6",
      "method": "token-endpoint requests against a lab tenant, using lab-created test apps",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/70",
      "scenario": "Federated credential: audience does not match",
      "expected": "700212 / 700213 / 70021",
      "got": "7002121",
      "matchedExpectation": false,
      "message": "AADSTS7002121: No matching federated identity record found for presented assertion audience '{audience-id}'. The Audience for the federat"
    },
    {
      "date": "2026-10-30",
      "run": "round 7",
      "method": "token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/71",
      "scenario": "Federated credential: audience does not match",
      "expected": "700212 / 700213 / 70021",
      "got": "7002121",
      "matchedExpectation": false,
      "message": "AADSTS7002121: No matching federated identity record found for presented assertion audience '{audience-id}'. The Audience for the federat"
    },
    {
      "date": "2026-10-31",
      "run": "round 8",
      "method": "token-endpoint and device-code requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/72",
      "scenario": "Federated credential: audience does not match",
      "expected": "700212 / 700213 / 70021",
      "got": "7002121",
      "matchedExpectation": false,
      "message": "AADSTS7002121: No matching federated identity record found for presented assertion audience '{audience-id}'. The Audience for the federat"
    },
    {
      "date": "2026-10-31",
      "run": "round 9",
      "method": "token-endpoint and device-code requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/73",
      "scenario": "Federated credential: audience does not match",
      "expected": "700212 / 700213 / 70021",
      "got": "7002121",
      "matchedExpectation": false,
      "message": "AADSTS7002121: No matching federated identity record found for presented assertion audience '{audience-id}'. The Audience for the federat"
    }
  ],
  "verification": "lab-reproduced",
  "related": [
    "700212",
    "700211",
    "700213",
    "7002138",
    "70025",
    "700226"
  ],
  "coveredBy": [],
  "sources": [
    {
      "title": "Microsoft Entra authentication and authorization error codes",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes"
    },
    {
      "title": "Important considerations and restrictions for federated identity credentials",
      "url": "https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-considerations"
    },
    {
      "title": "Overview of federated identity credentials (Microsoft Graph)",
      "url": "https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview"
    },
    {
      "title": "Configure an application to trust a managed identity",
      "url": "https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity"
    },
    {
      "title": "Microsoft Entra breaking changes: Federated Identity Credentials now use case-sensitive matching",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-breaking-changes"
    },
    {
      "title": "AADServicePrincipalSignInLogs table reference (Azure Monitor)",
      "url": "https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/aadserviceprincipalsigninlogs"
    }
  ],
  "published": "2026-10-30",
  "lastUpdated": "2026-10-30",
  "lastVerified": null,
  "license": "CC BY 4.0",
  "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
  "licenseNote": "CC BY 4.0 covers the author's own text and classification fields. Quoted Microsoft error wording belongs to Microsoft, is quoted with its source and can change.",
  "attribution": "Bram Brinkmeier, \"AADSTS7002121: Federated credential audience doesn't match the assertion (fix)\", https://brambrinkmeier.com/entra/aadsts/7002121/ (CC BY 4.0)",
  "microsoftErrorLookup": "https://login.microsoftonline.com/error?code=7002121"
}
