Skip to content

AADSTS70043: Refresh token expired due to sign-in frequency checks

Short answer: AADSTS70043 means a refresh token was refused because a Conditional Access sign-in frequency policy says the user must authenticate again. It is the session control working as configured, so it is expected and has low attack value. Volume tracks how strict your policy is. Hunt it in AADNonInteractiveUserSignInLogs with ResultType == "70043".

At a glance
CodeAADSTS70043
Microsoft nameBadTokenDueToSignInFrequency
CategoryTokens and sessions
TypeFailure
Attack signalLow: usually configuration or user error
Where to lookAADNonInteractiveUserSignInLogs
Microsoft lookuplogin.microsoftonline.com/error?code=70043

BadTokenDueToSignInFrequency: The refresh token has expired or is invalid due to sign-in frequency checks by Conditional Access. The token was issued on {issueDate} and the maximum allowed lifetime for this request is {time}.

An app tried to use a refresh token silently. A Conditional Access policy with a sign-in frequency session control says the user’s last authentication is too old for this request. The app has to send the user to an interactive sign-in.

No. 70043 is a control you configured doing its job. Expect it wherever you have a sign-in frequency policy, and expect more of it the shorter the interval.

Pattern Likely meaning
70043 for a user, followed by an interactive success in SigninLogs from the same IP and device Normal re-authentication. Benign.
A jump in 70043 volume on a specific day Someone created or tightened a sign-in frequency policy. Check your Conditional Access change history.
70043 for a user from an IP or device they don’t use, with no interactive sign-in following An old refresh token being presented from somewhere unexpected. This is reasoning, not a documented detection: the control stopped it, but the token existed somewhere it shouldn’t. Investigate as a possible stolen token.

The message includes the token’s issue date and the maximum allowed lifetime, so it tells you how old the token was when it was refused.

Which apps and policies generate the volume:

AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(7d)
| where ResultType == "70043"
| summarize Rows = count(),
Users = dcount(UserPrincipalName),
IPs = dcount(IPAddress)
by AppDisplayName, ResourceDisplayName
| sort by Rows desc

The rare case worth a look: 70043 from an IP where the same user had no successful sign-in in the previous 30 days.

let lookback = 30d;
let knownUserIPs =
union
(SigninLogs | project TimeGenerated, UserPrincipalName, IPAddress, ResultType),
(AADNonInteractiveUserSignInLogs | project TimeGenerated, UserPrincipalName, IPAddress, ResultType)
| where TimeGenerated > ago(lookback)
| where ResultType == "0"
| distinct UserPrincipalName, IPAddress;
AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(1d)
| where ResultType == "70043"
| join kind=leftanti knownUserIPs on UserPrincipalName, IPAddress
| extend Location = parse_json(LocationDetails)
| project TimeGenerated, UserPrincipalName, IPAddress,
Country = tostring(Location.countryOrRegion),
AppDisplayName, UserAgent, ResultDescription
| sort by TimeGenerated desc

ResultType is a string column, so compare it with "70043", not 70043. LocationDetails is a string in this table, hence parse_json. Non-interactive rows are aggregated when application, user, IP address, status and resource match, so row counts are not request counts.

  • The cause is a Conditional Access session control: sign-in frequency. Microsoft’s default, with no such policy, is “a rolling window of 90 days.”
  • A shorter interval means more 70043 rows and more prompts. Microsoft warns: “Triggering reauthentication too frequently can increase security friction to a point that it causes users to experience MFA fatigue and open the door to phishing.”
  • The re-authentication after a 70043 is a normal sign-in. It goes through MFA and the rest of your Conditional Access policies.

For the user: sign in again when the app asks.

For admins:

  1. Nothing is broken. If users complain about too many prompts, check which policy sets the interval with the first query and the policy list on the matching interactive sign-in.
  2. Reserve short sign-in frequency intervals for high-risk apps, users or unmanaged devices, rather than everyone.
  3. If the second query returns a row you can’t explain, treat the user’s tokens as exposed: revoke sessions and check the user’s recent sign-ins.

Sources

  1. Microsoft Entra authentication and authorization error codes
  2. Conditional Access: session lifetime
  3. Non-interactive user sign-ins
  4. AADNonInteractiveUserSignInLogs table reference (Azure Monitor)