# AADSTS50089: Flow token expired, sign in again (fix)

Canonical: https://brambrinkmeier.com/entra/aadsts/50089/
By Bram Brinkmeier. JSON: https://brambrinkmeier.com/api/aadsts/50089.json

**Short answer:** AADSTS50089 means a sign-in failed because a token that was part of the sign-in had expired. Microsoft calls it expected: auth codes, refresh tokens and sessions expire or get revoked, and the app asks the user to sign in again. It has low attack value. Filter it out of failure dashboards and look only at users who can't get past it.

**Fix:** Nothing to fix: the token expired as designed. User: sign in again. If it keeps happening, close the app or tab and start a fresh sign-in. Developer: treat 50089 as 'start a new sign-in' and redeem auth codes immediately. Admin: exclude 50089 from failure counts and spray rules.

| Field | Value |
|---|---|
| Code | AADSTS50089 |
| Category | Tokens and sessions |
| Type | Interrupt (an expected extra step, not a failure) |
| Attack signal | Low: usually configuration or user error |
| In Microsoft's error reference | Yes |
| Verification | documentation |
| Last updated | 2026-10-30 |

## What does AADSTS50089 mean?

Microsoft's description:

> Authentication failed due to flow token expired. Expected - auth codes, refresh tokens, and sessions expire over time or are revoked by the user or an admin. The app will request a new login from the user.

The reference table gives this code no PascalCase name.

Microsoft doesn't define "flow token" anywhere we could find. Our reading is that it refers to the state Entra keeps for a sign-in in progress, so a sign-in page left open too long before the user finishes would produce 50089. The description itself names three things that expire: auth codes, refresh tokens and sessions. Some documented lifetimes:

- **Authorization codes** are short lived. The authorization code flow reference: *"Typically, they expire after about 1 minute."*
- **Refresh tokens** have a default Max Inactive Time of 90 days.
- **Session tokens**: *"Non-persistent session tokens have a Max Inactive Time of 24 hours; persistent session tokens have a Max Inactive Time of 90 days."*

Several close relatives cover specific cases of "your old token or session no longer counts":

- **[50133](https://brambrinkmeier.com/entra/aadsts/50133/)**: the session is invalid after a password change or expiry.
- **[50173](https://brambrinkmeier.com/entra/aadsts/50173/)**: the grant was revoked, for example after a password reset.
- **[70043](https://brambrinkmeier.com/entra/aadsts/70043/)**: a Conditional Access sign-in frequency policy refused the refresh token.

For a comparison of the codes behind repeated sign-in prompts, see [why a user is asked to sign in again](https://brambrinkmeier.com/guides/why-user-asked-to-sign-in-again-entra-id/).

## Is it an attack?

No. Microsoft's description starts with *"Expected"*. The sign-in fails, nothing is issued, and the app starts over.

| Pattern | Likely meaning |
|---|---|
| A few 50089 rows per user, each followed by a success | A token or sign-in step expired and the user signed in again. Benign. |
| 50089 for many users of one app, all at the same time of day | Our interpretation: users who leave the sign-in page or app open overnight and continue the next morning. Benign. |
| 50089 for one user, repeating several times a day, often with no success after | Something on that device keeps presenting an expired token or session. Clear the app's cached sign-in or browser state. |
| 50089 together with 50133 or 50173 for the same user | A password change or revocation is working its way through the user's sessions. Benign if you know about the change. |

There is no documented attack pattern for 50089. An expired token gets the sender nothing. Keep it out of password spray detections and failure-rate thresholds.

## How do I find it in my logs (KQL)?

Microsoft doesn't document which sign-in table 50089 is logged in. Start by checking where it lands in your workspace:

```kusto
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(7d)
| where ResultType == "50089"
| summarize Rows = count(), Users = dcount(UserPrincipalName) by SourceTable
```

Which apps and client types produce it:

```kusto
union SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(7d)
| where ResultType == "50089"
| summarize Rows = count(), Users = dcount(UserPrincipalName) by AppDisplayName, ClientAppUsed
| sort by Rows desc
```

Users who hit 50089 again and again without a success afterwards on the same app the same day. These are the ones worth a support ticket:

```kusto
let expired =
    union SigninLogs, AADNonInteractiveUserSignInLogs
    | where TimeGenerated > ago(1d)
    | where ResultType == "50089"
    | summarize FirstFail = min(TimeGenerated), Fails = count() by UserPrincipalName, AppId, AppDisplayName;
let successes =
    union SigninLogs, AADNonInteractiveUserSignInLogs
    | where TimeGenerated > ago(1d)
    | where ResultType == "0"
    | summarize LastSuccess = max(TimeGenerated) by UserPrincipalName, AppId;
expired
| join kind=leftouter successes on UserPrincipalName, AppId
| where isnull(LastSuccess) or LastSuccess < FirstFail
| where Fails >= 5
| project UserPrincipalName, AppDisplayName, Fails, FirstFail
| sort by Fails desc
```

The threshold of 5 is a starting point; tune it to your tenant. Non-interactive rows are aggregated when application, user, IP address, status and resource match, so `Fails` counts rows there, not requests. `ResultType` is a **string** column, so compare it with `"50089"`, not `50089`.

## How does Conditional Access affect it?

- 50089 is not a Conditional Access block. No policy causes it directly.
- Session lifetime is now controlled with Conditional Access. Microsoft: refresh and session token lifetimes *"are no longer configurable through token lifetime policies"* and *"To control how frequently users are required to sign in, use Conditional Access sign-in frequency instead."*
- A sign-in frequency policy that refuses a refresh token shows up as [70043](https://brambrinkmeier.com/entra/aadsts/70043/), not 50089. If users complain about frequent prompts, check for 70043 first.
- Microsoft warns that combining **Remember MFA on trusted devices** with sign-in frequency *"might prompt users unexpectedly."*

## How do I fix AADSTS50089?

**For the user:** sign in again. If it keeps happening, close the app or browser tab completely and start a fresh sign-in instead of continuing an old one.

**For developers:** treat 50089 as "start a new sign-in", not as a fatal error. Microsoft says *"The app will request a new login from the user."* Redeem authorization codes immediately; they typically expire after about a minute. Don't build logic on the code number itself. Microsoft notes that *"Apps that take a dependency on text or error code numbers will be broken over time."* React to the OAuth `error` value instead.

**For admins:**
1. Nothing is broken. Exclude `"50089"` from failure counts and spray detections.
2. Use the third query for users stuck in a loop. Clear the app's cached sign-in on their device or browser.
3. If many users get unexpected sign-in prompts, review your Conditional Access session controls (sign-in frequency, persistent browser session) and turn off **Remember MFA on trusted devices** if you use sign-in frequency.

## Evidence

Not reproduced in the lab yet; the page is based on Microsoft's documentation.

## Sources

1. [Microsoft Entra authentication and authorization error codes](https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes)
2. [Configurable token lifetimes in the Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/configurable-token-lifetimes)
3. [Configure adaptive session lifetime policies](https://learn.microsoft.com/en-us/entra/identity/conditional-access/howto-conditional-access-session-lifetime)
4. [Microsoft identity platform and OAuth 2.0 authorization code flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow)
5. [Non-interactive user sign-ins](https://learn.microsoft.com/en-us/entra/identity/monitoring-health/concept-noninteractive-sign-ins)

## Related codes

[AADSTS50133](https://brambrinkmeier.com/entra/aadsts/50133/), [AADSTS50173](https://brambrinkmeier.com/entra/aadsts/50173/), [AADSTS70043](https://brambrinkmeier.com/entra/aadsts/70043/), [AADSTS700082](https://brambrinkmeier.com/entra/aadsts/700082/), [AADSTS50058](https://brambrinkmeier.com/entra/aadsts/50058/)

## License and citation

CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). 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.

Cite as: Bram Brinkmeier, "AADSTS50089: Flow token expired, sign in again (fix)", https://brambrinkmeier.com/entra/aadsts/50089/ (CC BY 4.0), last updated 2026-10-30.
