{
  "schemaVersion": "1.0",
  "code": "900144",
  "name": null,
  "title": "AADSTS900144: Request body is missing a required parameter (fix)",
  "url": "https://brambrinkmeier.com/entra/aadsts/900144/",
  "alternates": {
    "markdown": "https://brambrinkmeier.com/entra/aadsts/900144.md",
    "json": "https://brambrinkmeier.com/api/aadsts/900144.json",
    "html": "https://brambrinkmeier.com/entra/aadsts/900144/"
  },
  "description": "AADSTS900144: a token or sign-in request is missing a required parameter. A developer error with low attack value; the message names the parameter. KQL.",
  "summary": "AADSTS900144 means an app sent a request to Microsoft Entra ID without a parameter the flow requires, such as password, client_id or grant_type. Microsoft calls it a developer error. The error names the missing parameter. It has low attack value; fix the request the app builds. Look for it by app and error text in all three sign-in tables.",
  "inMicrosoftReference": true,
  "unlistedChecked": null,
  "meaningText": "Microsoft's description:\n\n> The request body must contain the following parameter: '{name}'. Developer error - the app is attempting to sign in without the necessary or correct authentication parameters.\n\nThe app sent a request to the Microsoft identity platform and left out a parameter that the flow requires. The error replaces `{name}` with the missing parameter, so the message tells you exactly what to add.\n\nWhich parameters are required depends on the flow. For the resource owner password credentials (ROPC) flow, for example, Microsoft lists `client_id`, `grant_type` (*\"Must be set to `password`\"*), `username` and `password` as **Required**. A confidential client must also send `client_secret` or `client_assertion`.",
  "sections": [
    {
      "heading": "What does AADSTS900144 mean?",
      "text": "Microsoft's description:\n\n> The request body must contain the following parameter: '{name}'. Developer error - the app is attempting to sign in without the necessary or correct authentication parameters.\n\nThe app sent a request to the Microsoft identity platform and left out a parameter that the flow requires. The error replaces `{name}` with the missing parameter, so the message tells you exactly what to add.\n\nWhich parameters are required depends on the flow. For the resource owner password credentials (ROPC) flow, for example, Microsoft lists `client_id`, `grant_type` (*\"Must be set to `password`\"*), `username` and `password` as **Required**. A confidential client must also send `client_secret` or `client_assertion`."
    },
    {
      "heading": "Reproduced in the lab",
      "text": "On 25 October 2026 an automated lab run sent an ROPC token request to my lab tenant without the `password` parameter. Entra returned `AADSTS900144` with this first line:\n\n> AADSTS900144: The request body must contain the following parameter: 'password'.\n\nThat confirms the code and its wording at the token endpoint, with `{name}` filled in as `password`. The sign-in log row was not captured, and the KQL on this page is not checked against it yet; see [how pages are checked](https://brambrinkmeier.com/methodology/)."
    },
    {
      "heading": "Is it an attack?",
      "text": "No documented attack pattern exists for 900144. Microsoft calls it a *\"Developer error\"*. The request is incomplete, so no credential is checked and nothing is issued. Our reading: an attacker learns nothing from it either.\n\n| Pattern | Likely meaning |\n|---|---|\n| 900144 from one app, starting right after a release | A bug in the new version builds the request without a parameter. Configuration. |\n| 900144 naming `client_secret` or `client_assertion` | Our interpretation: a confidential client sent no credential, often an empty secret in the configuration or a missing environment variable. |\n| 900144 naming `password` or `username` from a script or tool | A script built an ROPC request with an empty value. Usually a broken automation. |\n| 900144 from an unknown IP, for an app ID you don't recognise | Someone is calling the token endpoint with a hand-built request. Not an attack by itself, but worth checking who owns the client. |\n\nExclude it from failure-based attack detections. A password spray sends a password; it fails with codes such as [50126](https://brambrinkmeier.com/entra/aadsts/50126/), not 900144."
    },
    {
      "heading": "How do I find it in my logs (KQL)?",
      "text": "Microsoft doesn't document whether or where 900144 is logged, and the lab run above didn't capture a sign-in row, so we can't say yet whether one is written. Check all three sign-in tables:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"900144\"\n| summarize Rows = count(), Apps = dcount(AppId) by SourceTable\n```\n\nWhich app is missing which parameter. We assume `ResultDescription` carries the message with the parameter name filled in; we haven't checked that against a logged row:\n\n```kusto\nunion SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"900144\"\n| extend Parameter = extract(@\"parameter: '([^']+)'\", 1, ResultDescription)\n| summarize Rows = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated),\n            IPs = make_set(IPAddress, 5)\n          by AppDisplayName, AppId, Parameter\n| sort by Rows desc\n```\n\nNew sources: apps that produced 900144 today but not in the previous 14 days. A `FirstSeen` right after a deployment points to the release that broke it:\n\n```kusto\nlet recent =\n    union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n    | where TimeGenerated > ago(1d)\n    | where ResultType == \"900144\"\n    | summarize Rows = count(), FirstSeen = min(TimeGenerated) by AppId, AppDisplayName;\nlet before =\n    union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n    | where TimeGenerated between (ago(15d) .. ago(1d))\n    | where ResultType == \"900144\"\n    | distinct AppId;\nrecent\n| join kind=leftanti before on AppId\n| sort by Rows desc\n```\n\n`AppDisplayName` doesn't exist in `AADServicePrincipalSignInLogs`; there, use `ServicePrincipalName`. `ResultType` is a **string** column, so compare it with `\"900144\"`, not `900144`."
    },
    {
      "heading": "How do I fix AADSTS900144?",
      "text": "**For the user:** you can't fix this yourself. Report the error, with the parameter name from the message, to whoever runs the app.\n\n**For developers:**\n1. Read the parameter name in the error and add it to the request.\n2. Check the flow's parameter table in Microsoft's documentation. For ROPC, `client_id`, `grant_type`, `username` and `password` are required, and the request is a `POST` with `Content-Type: application/x-www-form-urlencoded`.\n3. Check that the parameter is in the request **body**, not the query string, as the message says. Our reading: a value that is empty or missing in your configuration ends up as no parameter at all.\n4. Prefer a Microsoft Authentication Library (MSAL) over hand-built requests. Microsoft also recommends against ROPC: *\"it's incompatible with multifactor authentication (MFA).\"*\n\n**For admins:**\n1. Use the second query to find the app and the parameter, and send both to the app's owner.\n2. If the app ID is unknown, look it up in Enterprise applications or App registrations. If nobody owns it, treat it like any unknown client calling your tenant."
    }
  ],
  "microsoftWording": {
    "text": "The request body must contain the following parameter: '{name}'. Developer error - the app is attempting to sign in without the necessary or correct authentication parameters.",
    "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": "config",
      "label": "Configuration error"
    },
    "attackSignal": {
      "level": "low",
      "label": "Low: usually configuration or user error"
    },
    "mitre": [],
    "tables": [
      "SigninLogs",
      "AADNonInteractiveUserSignInLogs",
      "AADServicePrincipalSignInLogs"
    ],
    "isItAnAttack": "No documented attack pattern exists for 900144. Microsoft calls it a *\"Developer error\"*. The request is incomplete, so no credential is checked and nothing is issued. Our reading: an attacker learns nothing from it either.\n\n| Pattern | Likely meaning |\n|---|---|\n| 900144 from one app, starting right after a release | A bug in the new version builds the request without a parameter. Configuration. |\n| 900144 naming `client_secret` or `client_assertion` | Our interpretation: a confidential client sent no credential, often an empty secret in the configuration or a missing environment variable. |\n| 900144 naming `password` or `username` from a script or tool | A script built an ROPC request with an empty value. Usually a broken automation. |\n| 900144 from an unknown IP, for an app ID you don't recognise | Someone is calling the token endpoint with a hand-built request. Not an attack by itself, but worth checking who owns the client. |\n\nExclude it from failure-based attack detections. A password spray sends a password; it fails with codes such as [50126](https://brambrinkmeier.com/entra/aadsts/50126/), not 900144.",
    "conditionalAccess": null
  },
  "kql": [
    {
      "title": null,
      "leadIn": "Microsoft doesn't document whether or where 900144 is logged, and the lab run above didn't capture a sign-in row, so we can't say yet whether one is written. Check all three sign-in tables:",
      "query": "union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"900144\"\n| summarize Rows = count(), Apps = dcount(AppId) by SourceTable"
    },
    {
      "title": null,
      "leadIn": "Which app is missing which parameter. We assume `ResultDescription` carries the message with the parameter name filled in; we haven't checked that against a logged row:",
      "query": "union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"900144\"\n| extend Parameter = extract(@\"parameter: '([^']+)'\", 1, ResultDescription)\n| summarize Rows = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated),\n            IPs = make_set(IPAddress, 5)\n          by AppDisplayName, AppId, Parameter\n| sort by Rows desc"
    },
    {
      "title": null,
      "leadIn": "New sources: apps that produced 900144 today but not in the previous 14 days. A `FirstSeen` right after a deployment points to the release that broke it:",
      "query": "let recent =\n    union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n    | where TimeGenerated > ago(1d)\n    | where ResultType == \"900144\"\n    | summarize Rows = count(), FirstSeen = min(TimeGenerated) by AppId, AppDisplayName;\nlet before =\n    union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n    | where TimeGenerated between (ago(15d) .. ago(1d))\n    | where ResultType == \"900144\"\n    | distinct AppId;\nrecent\n| join kind=leftanti before on AppId\n| sort by Rows desc"
    }
  ],
  "kqlSectionText": "Microsoft doesn't document whether or where 900144 is logged, and the lab run above didn't capture a sign-in row, so we can't say yet whether one is written. Check all three sign-in tables:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"900144\"\n| summarize Rows = count(), Apps = dcount(AppId) by SourceTable\n```\n\nWhich app is missing which parameter. We assume `ResultDescription` carries the message with the parameter name filled in; we haven't checked that against a logged row:\n\n```kusto\nunion SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"900144\"\n| extend Parameter = extract(@\"parameter: '([^']+)'\", 1, ResultDescription)\n| summarize Rows = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated),\n            IPs = make_set(IPAddress, 5)\n          by AppDisplayName, AppId, Parameter\n| sort by Rows desc\n```\n\nNew sources: apps that produced 900144 today but not in the previous 14 days. A `FirstSeen` right after a deployment points to the release that broke it:\n\n```kusto\nlet recent =\n    union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n    | where TimeGenerated > ago(1d)\n    | where ResultType == \"900144\"\n    | summarize Rows = count(), FirstSeen = min(TimeGenerated) by AppId, AppDisplayName;\nlet before =\n    union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n    | where TimeGenerated between (ago(15d) .. ago(1d))\n    | where ResultType == \"900144\"\n    | distinct AppId;\nrecent\n| join kind=leftanti before on AppId\n| sort by Rows desc\n```\n\n`AppDisplayName` doesn't exist in `AADServicePrincipalSignInLogs`; there, use `ServicePrincipalName`. `ResultType` is a **string** column, so compare it with `\"900144\"`, not `900144`.",
  "fix": {
    "short": "Developer: read the parameter name in the error and add it to the request body, not the query string. For ROPC, send `client_id`, `grant_type`, `username` and `password` as a form-encoded `POST`. User: report the error and the parameter name to whoever runs the app.",
    "steps": "**For the user:** you can't fix this yourself. Report the error, with the parameter name from the message, to whoever runs the app.\n\n**For developers:**\n1. Read the parameter name in the error and add it to the request.\n2. Check the flow's parameter table in Microsoft's documentation. For ROPC, `client_id`, `grant_type`, `username` and `password` are required, and the request is a `POST` with `Content-Type: application/x-www-form-urlencoded`.\n3. Check that the parameter is in the request **body**, not the query string, as the message says. Our reading: a value that is empty or missing in your configuration ends up as no parameter at all.\n4. Prefer a Microsoft Authentication Library (MSAL) over hand-built requests. Microsoft also recommends against ROPC: *\"it's incompatible with multifactor authentication (MFA).\"*\n\n**For admins:**\n1. Use the second query to find the app and the parameter, and send both to the app's owner.\n2. If the app ID is unknown, look it up in Enterprise applications or App registrations. If nobody owns it, treat it like any unknown client calling your tenant."
  },
  "labReproduced": {
    "date": "2026-10-25",
    "method": "ROPC token request against a lab tenant",
    "scenario": "Password parameter missing",
    "message": "AADSTS900144: The request body must contain the following parameter: 'password'.",
    "logCaptured": null,
    "kqlTested": null
  },
  "labSectionText": "On 25 October 2026 an automated lab run sent an ROPC token request to my lab tenant without the `password` parameter. Entra returned `AADSTS900144` with this first line:\n\n> AADSTS900144: The request body must contain the following parameter: 'password'.\n\nThat confirms the code and its wording at the token endpoint, with `{name}` filled in as `password`. The sign-in log row was not captured, and the KQL on this page is not checked against it yet; see [how pages are checked](https://brambrinkmeier.com/methodology/).",
  "labRuns": [
    {
      "date": "2026-10-25",
      "run": null,
      "method": "ROPC token request against a lab tenant",
      "issue": "https://github.com/GrantZero604/Brambrinkmeier.com/issues/38",
      "scenario": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    },
    {
      "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": "Password parameter missing",
      "expected": "900144",
      "got": "900144",
      "matchedExpectation": true,
      "message": "AADSTS900144: The request body must contain the following parameter: 'password'."
    }
  ],
  "verification": "lab-reproduced",
  "related": [
    "7000215",
    "700016",
    "50126",
    "90014",
    "90015",
    "900023",
    "900561",
    "901002"
  ],
  "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 Resource Owner Password Credentials",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth-ropc"
    },
    {
      "title": "SigninLogs table reference (Azure Monitor)",
      "url": "https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/signinlogs"
    },
    {
      "title": "AADNonInteractiveUserSignInLogs table reference (Azure Monitor)",
      "url": "https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/aadnoninteractiveusersigninlogs"
    },
    {
      "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, \"AADSTS900144: Request body is missing a required parameter (fix)\", https://brambrinkmeier.com/entra/aadsts/900144/ (CC BY 4.0)",
  "microsoftErrorLookup": "https://login.microsoftonline.com/error?code=900144"
}
