{
  "schemaVersion": "1.0",
  "code": "9002313",
  "name": "InvalidRequest",
  "title": "AADSTS9002313: Request is malformed or invalid (fix)",
  "url": "https://brambrinkmeier.com/entra/aadsts/9002313/",
  "alternates": {
    "markdown": "https://brambrinkmeier.com/entra/aadsts/9002313.md",
    "json": "https://brambrinkmeier.com/api/aadsts/9002313.json",
    "html": "https://brambrinkmeier.com/entra/aadsts/9002313/"
  },
  "description": "AADSTS9002313: the sign-in or token request was malformed. A developer error with low attack value; capture a trace and fix the request. KQL.",
  "summary": "AADSTS9002313 means Microsoft Entra ID couldn't process a sign-in or token request because the request itself was malformed. It is a developer or integration error, not a credential failure. Microsoft's own advice is to capture a Fiddler trace and check how the request is built. It has low attack value. Find which app sends the bad requests and fix the request.",
  "inMicrosoftReference": true,
  "unlistedChecked": null,
  "meaningText": "Microsoft's description:\n\n> **InvalidRequest**: Request is malformed or invalid. - The issue arises because there was something wrong with the request to a certain endpoint. The suggestion to this issue is to get a fiddler trace of the error occurring and looking to see if the request is properly formatted or not.\n\nThe request never got as far as checking a password or a secret. Something in how it was built was wrong, so Microsoft Entra ID rejected it as a request.\n\nMicrosoft's description doesn't say which part of the request is wrong. That is the hard part of this code: it is generic. The OAuth 2.0 protocol error that goes with this kind of problem is `invalid_request`, which the authorization code flow reference describes as a *\"Protocol error, such as a missing required parameter.\"* Its advice for the client: *\"Fix and resubmit the request. This error is a development error typically caught during initial testing.\"* Our reading is that 9002313 is the AADSTS code behind many of those `invalid_request` responses, but Microsoft doesn't publish that mapping.",
  "sections": [
    {
      "heading": "What does AADSTS9002313 mean?",
      "text": "Microsoft's description:\n\n> **InvalidRequest**: Request is malformed or invalid. - The issue arises because there was something wrong with the request to a certain endpoint. The suggestion to this issue is to get a fiddler trace of the error occurring and looking to see if the request is properly formatted or not.\n\nThe request never got as far as checking a password or a secret. Something in how it was built was wrong, so Microsoft Entra ID rejected it as a request.\n\nMicrosoft's description doesn't say which part of the request is wrong. That is the hard part of this code: it is generic. The OAuth 2.0 protocol error that goes with this kind of problem is `invalid_request`, which the authorization code flow reference describes as a *\"Protocol error, such as a missing required parameter.\"* Its advice for the client: *\"Fix and resubmit the request. This error is a development error typically caught during initial testing.\"* Our reading is that 9002313 is the AADSTS code behind many of those `invalid_request` responses, but Microsoft doesn't publish that mapping."
    },
    {
      "heading": "Is it an attack?",
      "text": "Almost never. A malformed request gets the sender nothing, and Microsoft treats the code as a request-formatting problem.\n\n| Pattern | Likely meaning |\n|---|---|\n| 9002313 for one app, starting right after a deployment or library update | The new version builds its requests differently. A regression in the app. |\n| 9002313 for every user of one app, from the start | The integration was never built correctly. Common with hand-written OAuth code. |\n| 9002313 for one user only | Something specific to that user's request, such as a stale bookmark to a sign-in URL or a broken browser extension. Likely, but unconfirmed. |\n| 9002313 from an IP you don't know, for an app ID you don't recognise | Someone's tooling is building bad requests against your tenant. Our interpretation: it is worth a look at what else that IP did, but the 9002313 itself is not harmful. |\n\nThere is no documented attack pattern for 9002313. Keep it out of password spray detections, because it says nothing about credentials."
    },
    {
      "heading": "How do I find it in my logs (KQL)?",
      "text": "Microsoft doesn't document which sign-in table 9002313 is logged in, or whether every malformed request produces a sign-in log row at all. Start by checking where it lands in your workspace:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"9002313\"\n| summarize Rows = count(), Apps = dcount(AppId) by SourceTable\n```\n\nWhich apps send the malformed requests, and since when. A sudden start date usually points at a release:\n\n```kusto\nunion SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"9002313\"\n| summarize Rows = count(),\n            FirstSeen = min(TimeGenerated),\n            LastSeen = max(TimeGenerated),\n            IPs = dcount(IPAddress),\n            Descriptions = make_set(ResultDescription, 5)\n          by AppId, AppDisplayName = coalesce(AppDisplayName, ServicePrincipalName)\n| sort by Rows desc\n```\n\nCheck `ResultDescription` in the output. It may carry more detail than the generic reference text, such as the name of the parameter that was wrong. Whether it does isn't documented, so treat it as a bonus if it's there.\n\nNon-interactive and service principal rows are aggregated when application, user (or service principal), IP address, status and resource match, so row counts in those tables are not request counts. `ResultType` is a **string** column, so compare it with `\"9002313\"`, not `9002313`."
    },
    {
      "heading": "How do I fix AADSTS9002313?",
      "text": "**For the user:** this isn't something you caused with your password. If an old bookmark or saved link starts the sign-in, open the app from its normal start page instead. If the error stays, report it to whoever runs the app with the time it happened.\n\n**For developers:**\n1. Do what Microsoft suggests: capture the failing request with Fiddler (or your browser's developer tools) and check it parameter by parameter against the protocol reference for that endpoint.\n2. Check that the request goes to the right endpoint for its parameters. A v2.0 parameter such as `scope` sent to a v1 endpoint, or the reverse, is a typical way to build an invalid request. That is our example, not one Microsoft lists for this code.\n3. Check encoding. Values in a token request body must be form-encoded; a raw `+`, `&` or space in a secret or redirect URI breaks the request. Again our example, not a Microsoft statement.\n4. Prefer a Microsoft Authentication Library (MSAL) over hand-written requests. It builds the protocol messages for you.\n\n**For admins:**\n1. Use the second query to find the app and the date it started. Hand both to the app owner or vendor.\n2. If the app is a third-party SaaS integration, the request is built on the vendor side. Open a ticket with them and include the correlation ID and timestamp from the sign-in log row.\n3. If the app ID is unknown to you, check whether it has a service principal in your tenant before deciding it is harmless. A related code for an app that isn't there is [700016](https://brambrinkmeier.com/entra/aadsts/700016/)."
    }
  ],
  "microsoftWording": {
    "text": "**InvalidRequest**: Request is malformed or invalid. - The issue arises because there was something wrong with the request to a certain endpoint. The suggestion to this issue is to get a fiddler trace of the error occurring and looking to see if the request is properly formatted or not.",
    "source": "Microsoft's error code reference, as quoted on the page",
    "sourceUrl": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes"
  },
  "securityReading": {
    "category": {
      "id": "app-config",
      "label": "App configuration"
    },
    "kind": {
      "id": "failure",
      "label": "Failure"
    },
    "attackSignal": {
      "level": "low",
      "label": "Low: usually configuration or user error"
    },
    "mitre": [],
    "tables": [],
    "isItAnAttack": "Almost never. A malformed request gets the sender nothing, and Microsoft treats the code as a request-formatting problem.\n\n| Pattern | Likely meaning |\n|---|---|\n| 9002313 for one app, starting right after a deployment or library update | The new version builds its requests differently. A regression in the app. |\n| 9002313 for every user of one app, from the start | The integration was never built correctly. Common with hand-written OAuth code. |\n| 9002313 for one user only | Something specific to that user's request, such as a stale bookmark to a sign-in URL or a broken browser extension. Likely, but unconfirmed. |\n| 9002313 from an IP you don't know, for an app ID you don't recognise | Someone's tooling is building bad requests against your tenant. Our interpretation: it is worth a look at what else that IP did, but the 9002313 itself is not harmful. |\n\nThere is no documented attack pattern for 9002313. Keep it out of password spray detections, because it says nothing about credentials.",
    "conditionalAccess": null
  },
  "kql": [
    {
      "title": null,
      "leadIn": "Microsoft doesn't document which sign-in table 9002313 is logged in, or whether every malformed request produces a sign-in log row at all. Start by checking where it lands in your workspace:",
      "query": "union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"9002313\"\n| summarize Rows = count(), Apps = dcount(AppId) by SourceTable"
    },
    {
      "title": null,
      "leadIn": "Which apps send the malformed requests, and since when. A sudden start date usually points at a release:",
      "query": "union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"9002313\"\n| summarize Rows = count(),\n            FirstSeen = min(TimeGenerated),\n            LastSeen = max(TimeGenerated),\n            IPs = dcount(IPAddress),\n            Descriptions = make_set(ResultDescription, 5)\n          by AppId, AppDisplayName = coalesce(AppDisplayName, ServicePrincipalName)\n| sort by Rows desc"
    }
  ],
  "kqlSectionText": "Microsoft doesn't document which sign-in table 9002313 is logged in, or whether every malformed request produces a sign-in log row at all. Start by checking where it lands in your workspace:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"9002313\"\n| summarize Rows = count(), Apps = dcount(AppId) by SourceTable\n```\n\nWhich apps send the malformed requests, and since when. A sudden start date usually points at a release:\n\n```kusto\nunion SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"9002313\"\n| summarize Rows = count(),\n            FirstSeen = min(TimeGenerated),\n            LastSeen = max(TimeGenerated),\n            IPs = dcount(IPAddress),\n            Descriptions = make_set(ResultDescription, 5)\n          by AppId, AppDisplayName = coalesce(AppDisplayName, ServicePrincipalName)\n| sort by Rows desc\n```\n\nCheck `ResultDescription` in the output. It may carry more detail than the generic reference text, such as the name of the parameter that was wrong. Whether it does isn't documented, so treat it as a bonus if it's there.\n\nNon-interactive and service principal rows are aggregated when application, user (or service principal), IP address, status and resource match, so row counts in those tables are not request counts. `ResultType` is a **string** column, so compare it with `\"9002313\"`, not `9002313`.",
  "fix": {
    "short": "Developer: capture the failing request with Fiddler or browser developer tools and check it parameter by parameter against the endpoint's protocol reference; use MSAL instead of hand-written requests. Admin: find the app and start date with the second query and give both to the app owner or vendor.",
    "steps": "**For the user:** this isn't something you caused with your password. If an old bookmark or saved link starts the sign-in, open the app from its normal start page instead. If the error stays, report it to whoever runs the app with the time it happened.\n\n**For developers:**\n1. Do what Microsoft suggests: capture the failing request with Fiddler (or your browser's developer tools) and check it parameter by parameter against the protocol reference for that endpoint.\n2. Check that the request goes to the right endpoint for its parameters. A v2.0 parameter such as `scope` sent to a v1 endpoint, or the reverse, is a typical way to build an invalid request. That is our example, not one Microsoft lists for this code.\n3. Check encoding. Values in a token request body must be form-encoded; a raw `+`, `&` or space in a secret or redirect URI breaks the request. Again our example, not a Microsoft statement.\n4. Prefer a Microsoft Authentication Library (MSAL) over hand-written requests. It builds the protocol messages for you.\n\n**For admins:**\n1. Use the second query to find the app and the date it started. Hand both to the app owner or vendor.\n2. If the app is a third-party SaaS integration, the request is built on the vendor side. Open a ticket with them and include the correlation ID and timestamp from the sign-in log row.\n3. If the app ID is unknown to you, check whether it has a service principal in your tenant before deciding it is harmless. A related code for an app that isn't there is [700016](https://brambrinkmeier.com/entra/aadsts/700016/)."
  },
  "labReproduced": null,
  "labSectionText": null,
  "labRuns": [
    {
      "date": "2026-10-30",
      "run": "round 4",
      "method": "token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/67",
      "scenario": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "date": "2026-10-30",
      "run": "round 4",
      "method": "token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/67",
      "scenario": "Client assertion that is not a JWT",
      "expected": "9002313 / 50027 / 700027",
      "got": "50027",
      "matchedExpectation": true,
      "message": "AADSTS50027: JWT token is invalid or malformed."
    },
    {
      "date": "2026-10-30",
      "run": "round 4",
      "method": "token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/67",
      "scenario": "Unknown client_assertion_type",
      "expected": "9002313 / 700027",
      "got": "90023",
      "matchedExpectation": false,
      "message": "AADSTS90023: Unexpected client assertion type."
    },
    {
      "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": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "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": "Client assertion that is not a JWT",
      "expected": "9002313 / 50027 / 700027",
      "got": "50027",
      "matchedExpectation": true,
      "message": "AADSTS50027: JWT token is invalid or malformed."
    },
    {
      "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": "Unknown client_assertion_type",
      "expected": "9002313 / 700027",
      "got": "90023",
      "matchedExpectation": false,
      "message": "AADSTS90023: Unexpected client assertion type."
    },
    {
      "date": "2026-10-30",
      "run": "round 5 (first attempt)",
      "method": "token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/68",
      "scenario": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "date": "2026-10-30",
      "run": "round 5 (first attempt)",
      "method": "token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/68",
      "scenario": "Client assertion that is not a JWT",
      "expected": "9002313 / 50027 / 700027",
      "got": "50027",
      "matchedExpectation": true,
      "message": "AADSTS50027: JWT token is invalid or malformed."
    },
    {
      "date": "2026-10-30",
      "run": "round 5 (first attempt)",
      "method": "token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/68",
      "scenario": "Unknown client_assertion_type",
      "expected": "9002313 / 700027",
      "got": "90023",
      "matchedExpectation": false,
      "message": "AADSTS90023: Unexpected client assertion type."
    },
    {
      "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": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "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": "Client assertion that is not a JWT",
      "expected": "9002313 / 50027 / 700027",
      "got": "50027",
      "matchedExpectation": true,
      "message": "AADSTS50027: JWT token is invalid or malformed."
    },
    {
      "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": "Unknown client_assertion_type",
      "expected": "9002313 / 700027",
      "got": "90023",
      "matchedExpectation": false,
      "message": "AADSTS90023: Unexpected client assertion type."
    },
    {
      "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": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "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": "Client assertion that is not a JWT",
      "expected": "9002313 / 50027 / 700027",
      "got": "50027",
      "matchedExpectation": true,
      "message": "AADSTS50027: JWT token is invalid or malformed."
    },
    {
      "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": "Unknown client_assertion_type",
      "expected": "9002313 / 700027",
      "got": "90023",
      "matchedExpectation": false,
      "message": "AADSTS90023: Unexpected client assertion type."
    },
    {
      "date": "2026-10-30",
      "run": null,
      "method": "ROPC and other token-endpoint requests against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/66",
      "scenario": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "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": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "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": "Client assertion that is not a JWT",
      "expected": "9002313 / 50027 / 700027",
      "got": "50027",
      "matchedExpectation": true,
      "message": "AADSTS50027: JWT token is invalid or malformed."
    },
    {
      "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": "Unknown client_assertion_type",
      "expected": "9002313 / 700027",
      "got": "90023",
      "matchedExpectation": false,
      "message": "AADSTS90023: Unexpected client assertion type."
    },
    {
      "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": "Device code that was never issued",
      "expected": "70020 / 70000 / 9002313",
      "got": "7000014",
      "matchedExpectation": false,
      "message": "AADSTS7000014: The provided value for the input parameter 'device_code' is not valid."
    },
    {
      "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": "Client assertion that is not a JWT",
      "expected": "9002313 / 50027 / 700027",
      "got": "50027",
      "matchedExpectation": true,
      "message": "AADSTS50027: JWT token is invalid or malformed."
    },
    {
      "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": "Unknown client_assertion_type",
      "expected": "9002313 / 700027",
      "got": "90023",
      "matchedExpectation": false,
      "message": "AADSTS90023: Unexpected client assertion type."
    }
  ],
  "verification": "documentation",
  "related": [
    "50011",
    "7000215",
    "500011",
    "700016",
    "90014",
    "90015",
    "750054",
    "900023",
    "900561",
    "901002",
    "1002016",
    "7000014",
    "9002326",
    "9002327",
    "9002331",
    "9010010"
  ],
  "coveredBy": [],
  "sources": [
    {
      "title": "Microsoft Entra authentication and authorization error codes",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes"
    },
    {
      "title": "Microsoft identity platform and OAuth 2.0 authorization code flow",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow"
    },
    {
      "title": "Non-interactive user sign-ins",
      "url": "https://learn.microsoft.com/en-us/entra/identity/monitoring-health/concept-noninteractive-sign-ins"
    },
    {
      "title": "Service principal sign-ins",
      "url": "https://learn.microsoft.com/en-us/entra/identity/monitoring-health/concept-service-principal-sign-ins"
    }
  ],
  "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, \"AADSTS9002313: Request is malformed or invalid (fix)\", https://brambrinkmeier.com/entra/aadsts/9002313/ (CC BY 4.0)",
  "microsoftErrorLookup": "https://login.microsoftonline.com/error?code=9002313"
}
