{
  "schemaVersion": "1.0",
  "code": "70044",
  "name": null,
  "title": "AADSTS70044: Session expired by sign-in frequency checks (fix)",
  "url": "https://brambrinkmeier.com/entra/aadsts/70044/",
  "alternates": {
    "markdown": "https://brambrinkmeier.com/entra/aadsts/70044.md",
    "json": "https://brambrinkmeier.com/api/aadsts/70044.json",
    "html": "https://brambrinkmeier.com/entra/aadsts/70044/"
  },
  "description": "AADSTS70044: a Conditional Access sign-in frequency check ended the session. Not in Microsoft's reference. What it means, how to fix it, with KQL.",
  "summary": "AADSTS70044 means a Conditional Access sign-in frequency check ended the user's session, so the app must send the user to an interactive sign-in. Microsoft's error reference doesn't list it; the wording comes from a Microsoft Q&A answer. It is the session control working, with low attack value. The app should handle it by prompting, not by retrying silently.",
  "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 AADSTS70044 (checked 30 October 2026).\n\nThe wording below comes from a Microsoft Q&A thread, not from a Microsoft documentation page. A Q&A moderator (AmanpreetSingh-MSFT) quoted it in an answer:\n\n> AADSTS70044: The session has expired or is invalid due to sign-in frequency checks by conditional access.\n\nThe person who asked quoted the sign-in log failure reason as *\"The session has expired or is invalid due to sign-in frequency checks by conditional access. MFA requirement satisfied by claim in the token.\"*\n\nIn that thread, a Conditional Access policy set sign-in frequency to one hour for a VPN app. The moderator said the backend trace showed the credential was authenticated on one day and presented the next, outside the one-hour window, so it was ignored. The same thread says old credentials are usually reused during silent authentication, through a refresh token or a Primary Refresh Token (PRT).\n\nA second Q&A thread describes users with several browsers hitting \"error code 70044\" under a 30-day sign-in frequency policy. That thread gives no full message text.\n\nOur reading: 70044 is the session-side sibling of [70043](https://brambrinkmeier.com/entra/aadsts/70043/), which Microsoft does list. 70043 says the **refresh token** is too old for the sign-in frequency policy. 70044 says the **session** is. Both mean the same thing for the user: sign in again. Microsoft doesn't document the difference.",
  "sections": [
    {
      "heading": "What does AADSTS70044 mean?",
      "text": "Microsoft's [error code reference](https://learn.microsoft.com/entra/identity-platform/reference-error-codes) doesn't list AADSTS70044 (checked 30 October 2026).\n\nThe wording below comes from a Microsoft Q&A thread, not from a Microsoft documentation page. A Q&A moderator (AmanpreetSingh-MSFT) quoted it in an answer:\n\n> AADSTS70044: The session has expired or is invalid due to sign-in frequency checks by conditional access.\n\nThe person who asked quoted the sign-in log failure reason as *\"The session has expired or is invalid due to sign-in frequency checks by conditional access. MFA requirement satisfied by claim in the token.\"*\n\nIn that thread, a Conditional Access policy set sign-in frequency to one hour for a VPN app. The moderator said the backend trace showed the credential was authenticated on one day and presented the next, outside the one-hour window, so it was ignored. The same thread says old credentials are usually reused during silent authentication, through a refresh token or a Primary Refresh Token (PRT).\n\nA second Q&A thread describes users with several browsers hitting \"error code 70044\" under a 30-day sign-in frequency policy. That thread gives no full message text.\n\nOur reading: 70044 is the session-side sibling of [70043](https://brambrinkmeier.com/entra/aadsts/70043/), which Microsoft does list. 70043 says the **refresh token** is too old for the sign-in frequency policy. 70044 says the **session** is. Both mean the same thing for the user: sign in again. Microsoft doesn't document the difference."
    },
    {
      "heading": "Is it an attack?",
      "text": "Usually not. Users report it where a sign-in frequency policy exists, and it is the policy doing what it was configured to do.\n\n| Pattern | Likely meaning |\n|---|---|\n| 70044 for many users shortly after a new or tightened sign-in frequency policy | The policy is now enforced. Expected. |\n| 70044 for one user, repeating every few minutes, never followed by a success | The app keeps retrying silently and never prompts. An app bug, not an attack. Our interpretation. |\n| 70044 for a user who works in several browsers | Each browser keeps its own cookies and session, so a new browser or cleared cookies starts a new sign-in. This is from a Q&A answer, not from Microsoft documentation. |\n| 70044 from an IP or device the user never uses | An old session presented from somewhere unexpected. Our reasoning, not a documented detection: the control stopped it, but check the user's other sign-ins. |\n\nOne user report adds a caution. In Q&A 852942, revoking the user's sessions fixed the error only until the next day, and the person who asked later concluded the real cause was AD FS extranet lockout. That is their own conclusion, not a Microsoft answer, but it shows that 70044 can be the visible symptom of a different problem in federated tenants."
    },
    {
      "heading": "How do I find it in my logs (KQL)?",
      "text": "Microsoft doesn't document which sign-in table 70044 is logged in. Check where it lands in your workspace first:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"70044\"\n| summarize Rows = count() by SourceTable\n```\n\nWhich apps and session policies produce it. `SessionLifetimePolicies` is documented as *\"any conditional access session management policies that were applied during the sign-in event.\"* It is a string in both tables:\n\n```kusto\nunion\n    (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName, ClientAppUsed, SessionLifetimePolicies),\n    (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName, ClientAppUsed, SessionLifetimePolicies)\n| where TimeGenerated > ago(7d)\n| where ResultType == \"70044\"\n| summarize Rows = count(), Users = dcount(UserPrincipalName) by AppDisplayName, ClientAppUsed, SessionLifetimePolicies\n| sort by Rows desc\n```\n\nUsers stuck in a loop: many 70044 rows in a day and no success on the same app. The threshold of 20 is a starting point; tune it to your volume.\n\n```kusto\nlet window = 1d;\nlet fails =\n    union\n        (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName),\n        (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName)\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"70044\"\n    | summarize Fails = count(), LastFail = max(TimeGenerated) by UserPrincipalName, AppDisplayName\n    | where Fails >= 20;\nlet successes =\n    union\n        (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName),\n        (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName)\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"0\"\n    | distinct UserPrincipalName, AppDisplayName;\nfails\n| join kind=leftanti successes on UserPrincipalName, AppDisplayName\n| sort by Fails desc\n```"
    },
    {
      "heading": "How does Conditional Access affect it?",
      "text": "- The trigger users report is a Conditional Access **sign-in frequency** session control. Microsoft's default without such a policy is *\"a rolling window of 90 days.\"*\n- With **Every time**, Microsoft says the policy *\"requires full reauthentication when the session is evaluated\"* and *\"factors in five minutes of clock skew\"*. Microsoft also warns that every-time reauthentication without MFA *\"might result in sign-in looping for your users.\"*\n- On Microsoft Entra joined and hybrid joined devices, Microsoft says unlocking the device or signing in interactively refreshes the PRT every four hours, and the PRT's last refresh must fall inside the sign-in frequency window. On Microsoft Entra registered devices, unlocking doesn't satisfy the policy."
    },
    {
      "heading": "How do I fix AADSTS70044?",
      "text": "**For the user:** sign in again when the app asks. If the app never shows a sign-in prompt and keeps failing, close it fully, open it again, and sign in. If that doesn't help, tell IT the app name and the time.\n\n**For developers:** treat 70044 like any interaction-required result. Don't retry silently. The Q&A moderator's advice: force an interactive sign-in with `prompt=login` for OAuth and OpenID Connect, or `forceAuthN=true` for SAML. In the thread, `forceAuthN=true` worked but made every user type their username again, so use it only on this error, not on every sign-in.\n\n**For admins:**\n1. Find the policy. Open the failed sign-in in the Microsoft Entra admin center and check the Conditional Access tab, or use the second query above.\n2. If the interval is shorter than the app can handle, lengthen it or scope the policy to the apps and users that need it. Microsoft advises to *\"limit the number of applications that enforce a policy requiring users to reauthenticate every time.\"*\n3. For a single user who keeps failing on a joined device, check that the device's PRT refreshes. The Q&A moderator suggested comparing the event log **Applications and Services Logs > Microsoft > Windows > AAD > Operational** between a working and a failing user.\n4. In a federated tenant, rule out AD FS problems such as extranet lockout before you change the policy. That cause comes from one user report."
    }
  ],
  "microsoftWording": {
    "text": "AADSTS70044: The session has expired or is invalid due to sign-in frequency checks by conditional access.",
    "source": "Quoted on the page from the lab or from user reports; the code is not in Microsoft's error code reference",
    "sourceUrl": null
  },
  "securityReading": {
    "category": {
      "id": "token",
      "label": "Tokens and sessions"
    },
    "kind": {
      "id": "failure",
      "label": "Failure"
    },
    "attackSignal": {
      "level": "low",
      "label": "Low: usually configuration or user error"
    },
    "mitre": [],
    "tables": [],
    "isItAnAttack": "Usually not. Users report it where a sign-in frequency policy exists, and it is the policy doing what it was configured to do.\n\n| Pattern | Likely meaning |\n|---|---|\n| 70044 for many users shortly after a new or tightened sign-in frequency policy | The policy is now enforced. Expected. |\n| 70044 for one user, repeating every few minutes, never followed by a success | The app keeps retrying silently and never prompts. An app bug, not an attack. Our interpretation. |\n| 70044 for a user who works in several browsers | Each browser keeps its own cookies and session, so a new browser or cleared cookies starts a new sign-in. This is from a Q&A answer, not from Microsoft documentation. |\n| 70044 from an IP or device the user never uses | An old session presented from somewhere unexpected. Our reasoning, not a documented detection: the control stopped it, but check the user's other sign-ins. |\n\nOne user report adds a caution. In Q&A 852942, revoking the user's sessions fixed the error only until the next day, and the person who asked later concluded the real cause was AD FS extranet lockout. That is their own conclusion, not a Microsoft answer, but it shows that 70044 can be the visible symptom of a different problem in federated tenants.",
    "conditionalAccess": {
      "heading": "How does Conditional Access affect it?",
      "text": "- The trigger users report is a Conditional Access **sign-in frequency** session control. Microsoft's default without such a policy is *\"a rolling window of 90 days.\"*\n- With **Every time**, Microsoft says the policy *\"requires full reauthentication when the session is evaluated\"* and *\"factors in five minutes of clock skew\"*. Microsoft also warns that every-time reauthentication without MFA *\"might result in sign-in looping for your users.\"*\n- On Microsoft Entra joined and hybrid joined devices, Microsoft says unlocking the device or signing in interactively refreshes the PRT every four hours, and the PRT's last refresh must fall inside the sign-in frequency window. On Microsoft Entra registered devices, unlocking doesn't satisfy the policy."
    }
  },
  "kql": [
    {
      "title": null,
      "leadIn": "Microsoft doesn't document which sign-in table 70044 is logged in. Check where it lands in your workspace first:",
      "query": "union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"70044\"\n| summarize Rows = count() by SourceTable"
    },
    {
      "title": null,
      "leadIn": "Which apps and session policies produce it. `SessionLifetimePolicies` is documented as *\"any conditional access session management policies that were applied during the sign-in event.\"* It is a string in both tables:",
      "query": "union\n    (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName, ClientAppUsed, SessionLifetimePolicies),\n    (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName, ClientAppUsed, SessionLifetimePolicies)\n| where TimeGenerated > ago(7d)\n| where ResultType == \"70044\"\n| summarize Rows = count(), Users = dcount(UserPrincipalName) by AppDisplayName, ClientAppUsed, SessionLifetimePolicies\n| sort by Rows desc"
    },
    {
      "title": null,
      "leadIn": "Users stuck in a loop: many 70044 rows in a day and no success on the same app. The threshold of 20 is a starting point; tune it to your volume.",
      "query": "let window = 1d;\nlet fails =\n    union\n        (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName),\n        (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName)\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"70044\"\n    | summarize Fails = count(), LastFail = max(TimeGenerated) by UserPrincipalName, AppDisplayName\n    | where Fails >= 20;\nlet successes =\n    union\n        (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName),\n        (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName)\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"0\"\n    | distinct UserPrincipalName, AppDisplayName;\nfails\n| join kind=leftanti successes on UserPrincipalName, AppDisplayName\n| sort by Fails desc"
    }
  ],
  "kqlSectionText": "Microsoft doesn't document which sign-in table 70044 is logged in. Check where it lands in your workspace first:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"70044\"\n| summarize Rows = count() by SourceTable\n```\n\nWhich apps and session policies produce it. `SessionLifetimePolicies` is documented as *\"any conditional access session management policies that were applied during the sign-in event.\"* It is a string in both tables:\n\n```kusto\nunion\n    (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName, ClientAppUsed, SessionLifetimePolicies),\n    (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName, ClientAppUsed, SessionLifetimePolicies)\n| where TimeGenerated > ago(7d)\n| where ResultType == \"70044\"\n| summarize Rows = count(), Users = dcount(UserPrincipalName) by AppDisplayName, ClientAppUsed, SessionLifetimePolicies\n| sort by Rows desc\n```\n\nUsers stuck in a loop: many 70044 rows in a day and no success on the same app. The threshold of 20 is a starting point; tune it to your volume.\n\n```kusto\nlet window = 1d;\nlet fails =\n    union\n        (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName),\n        (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName)\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"70044\"\n    | summarize Fails = count(), LastFail = max(TimeGenerated) by UserPrincipalName, AppDisplayName\n    | where Fails >= 20;\nlet successes =\n    union\n        (SigninLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName),\n        (AADNonInteractiveUserSignInLogs | project TimeGenerated, ResultType, UserPrincipalName, AppDisplayName)\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"0\"\n    | distinct UserPrincipalName, AppDisplayName;\nfails\n| join kind=leftanti successes on UserPrincipalName, AppDisplayName\n| sort by Fails desc\n```",
  "fix": {
    "short": "User: sign in again when the app asks; if it never prompts, close the app fully, reopen it and sign in. Developer: don't retry silently; force an interactive sign-in with prompt=login (OAuth/OIDC) or forceAuthN=true (SAML) on this error only. Admin: check the sign-in frequency policy.",
    "steps": "**For the user:** sign in again when the app asks. If the app never shows a sign-in prompt and keeps failing, close it fully, open it again, and sign in. If that doesn't help, tell IT the app name and the time.\n\n**For developers:** treat 70044 like any interaction-required result. Don't retry silently. The Q&A moderator's advice: force an interactive sign-in with `prompt=login` for OAuth and OpenID Connect, or `forceAuthN=true` for SAML. In the thread, `forceAuthN=true` worked but made every user type their username again, so use it only on this error, not on every sign-in.\n\n**For admins:**\n1. Find the policy. Open the failed sign-in in the Microsoft Entra admin center and check the Conditional Access tab, or use the second query above.\n2. If the interval is shorter than the app can handle, lengthen it or scope the policy to the apps and users that need it. Microsoft advises to *\"limit the number of applications that enforce a policy requiring users to reauthenticate every time.\"*\n3. For a single user who keeps failing on a joined device, check that the device's PRT refreshes. The Q&A moderator suggested comparing the event log **Applications and Services Logs > Microsoft > Windows > AAD > Operational** between a working and a failing user.\n4. In a federated tenant, rule out AD FS problems such as extranet lockout before you change the policy. That cause comes from one user report."
  },
  "labReproduced": null,
  "labSectionText": null,
  "labRuns": [],
  "verification": "documentation",
  "related": [
    "70043",
    "700082",
    "50058",
    "50133",
    "53003"
  ],
  "coveredBy": [],
  "sources": [
    {
      "title": "Microsoft Entra authentication and authorization error codes",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes"
    },
    {
      "title": "Azure AD Signin Issue (Microsoft Q&A 852942)",
      "url": "https://learn.microsoft.com/en-us/answers/questions/852942/azure-ad-signin-issue"
    },
    {
      "title": "Conditional access and multiple browsers (Microsoft Q&A 5553648)",
      "url": "https://learn.microsoft.com/en-us/answers/questions/5553648/conditional-access-and-multiple-browsers"
    },
    {
      "title": "Conditional Access: session lifetime",
      "url": "https://learn.microsoft.com/en-us/entra/identity/conditional-access/concept-session-lifetime"
    },
    {
      "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"
    }
  ],
  "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, \"AADSTS70044: Session expired by sign-in frequency checks (fix)\", https://brambrinkmeier.com/entra/aadsts/70044/ (CC BY 4.0)",
  "microsoftErrorLookup": "https://login.microsoftonline.com/error?code=70044"
}
