Skip to content

fix(oauth): persist rotated Microsoft refresh tokens#4554

Merged
waleedlatif1 merged 2 commits into
stagingfrom
waleedlatif1/ms-oauth-refresh
May 11, 2026
Merged

fix(oauth): persist rotated Microsoft refresh tokens#4554
waleedlatif1 merged 2 commits into
stagingfrom
waleedlatif1/ms-oauth-refresh

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Microsoft Entra rotates refresh tokens on every refresh and expects the client to replace the stored token with the new one (see Microsoft docs).
  • The Microsoft provider config in apps/sim/lib/oauth/oauth.ts was missing supportsRefreshTokenRotation, so the rotated refresh_token from Azure AD was silently discarded and the original token from initial OAuth connect was reused indefinitely.
  • This caused periodic Failed to refresh access token failures (~monthly) for Excel, Teams, Outlook, OneDrive, SharePoint, Planner, AD, and Dataverse integrations even on daily-running workflows.
  • Fix: set supportsRefreshTokenRotation: true on the Microsoft branch. Persistence in apps/sim/app/api/auth/oauth/utils.ts already writes the new token back when returned.

Type of Change

  • Bug fix

Testing

  • Added unit test asserting all four Microsoft provider IDs (microsoft, outlook, onedrive, sharepoint) capture the rotated refresh_token from the token response.
  • Existing 31 oauth tests still pass.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Microsoft Entra rotates refresh tokens on every refresh and expects clients to replace the stored token with the new one. The Microsoft provider config was missing supportsRefreshTokenRotation, so the rotated refresh_token returned by Azure AD was silently discarded and the original token from initial OAuth connect was reused indefinitely — causing periodic 'Failed to refresh access token' errors for Excel, Teams, Outlook, OneDrive, SharePoint, Planner, AD, and Dataverse integrations.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 11, 2026 4:50pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 11, 2026

PR Summary

Medium Risk
Changes OAuth refresh behavior for Microsoft providers by enabling refresh-token rotation, which affects how long-lived credentials are stored and reused for multiple integrations. Scope is small and covered by tests, but mistakes could break token refresh for Microsoft services.

Overview
Fixes Microsoft OAuth refresh-token rotation. The Microsoft auth config now sets supportsRefreshTokenRotation: true, so refreshOAuthToken will return (and downstream persistence can store) the rotated refresh_token from Azure token refresh responses instead of continuing to reuse the original token.

Tests are extended to assert refresh-token rotation is applied across Microsoft base and service provider IDs (e.g., microsoft, outlook, onedrive, sharepoint, and related Microsoft services).

Reviewed by Cursor Bugbot for commit fd885f2. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 11, 2026

Greptile Summary

This PR fixes a token-refresh bug for Microsoft OAuth integrations by adding supportsRefreshTokenRotation: true to the Microsoft provider config in oauth.ts. Microsoft Entra rotates refresh tokens on every refresh, so without this flag the rotated token was silently discarded and the original token was reused indefinitely, causing eventual auth failures.

  • Core fix (oauth.ts): one-line addition of supportsRefreshTokenRotation: true in the microsoft/outlook/onedrive/sharepoint switch branch, which is already reused for all five hyphenated Microsoft sub-providers (microsoft-excel, microsoft-teams, etc.) via the existing getBaseProviderForService mapping that normalises any Microsoft sub-provider ID to 'microsoft' before calling getProviderAuthConfig.
  • Test (oauth.test.ts): a new concurrent test iterates over all nine Microsoft provider IDs and asserts that refreshOAuthToken returns the rotated refresh token; the persistence path in utils.ts (which saves the new token to the DB) was already correct before this change.

Confidence Score: 5/5

Safe to merge — the change is a targeted one-line flag addition with no behavioural side-effects for non-Microsoft providers.

The fix is minimal and isolated to the Microsoft provider branch. The getBaseProviderForService mapping already ensures all nine Microsoft sub-provider IDs resolve to the microsoft case before getProviderAuthConfig is called, so the single flag addition covers every affected integration. The persistence path in utils.ts already correctly saves the rotated token. The new test validates all nine providers end-to-end and the existing test suite is intact.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/oauth/oauth.ts Adds supportsRefreshTokenRotation: true to the Microsoft provider case; the change is minimal and correct — all hyphenated Microsoft sub-providers route through this case via getBaseProviderForService.
apps/sim/lib/oauth/oauth.test.ts New test covers all nine Microsoft provider IDs and verifies the rotated refresh token is returned; existing 31 tests are unaffected.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[refreshOAuthToken called with any Microsoft provider ID] --> B[getBaseProviderForService]
    B --> C{Is it a sub-provider?}
    C -- yes --> D[Map to base provider: microsoft]
    C -- no --> D
    D --> E[getProviderAuthConfig microsoft]
    E --> F[config with supportsRefreshTokenRotation enabled]
    F --> G[POST to Microsoft token endpoint]
    G --> H[Response contains rotated token]
    H --> I{supportsRefreshTokenRotation?}
    I -- true, after this fix --> J[Capture rotated token]
    I -- false, before this fix --> K[Discard rotated token, reuse old one]
    J --> L[Return new accessToken and rotated refreshToken]
    L --> M[Persist rotated token to DB]
Loading

Reviews (2): Last reviewed commit: "test(oauth): cover hyphenated Microsoft ..." | Re-trigger Greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile-apps the hyphenated Microsoft provider IDs (microsoft-excel, microsoft-teams, microsoft-planner, microsoft-ad, microsoft-dataverse) are not affected. refreshOAuthToken calls getBaseProviderForService first (oauth.ts:1486), which walks OAUTH_PROVIDERS.microsoft.services and maps these service IDs to the microsoft base provider before getProviderAuthConfig runs. They all hit the same case this PR fixes.

Pushed fd885f2 to extend the rotation test to cover all 9 Microsoft service IDs explicitly — all pass, confirming rotation works end-to-end for every Microsoft integration.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 11, 2026

That's correct and well-explained. Looking at the code flow:

  1. getBaseProviderForService iterates OAUTH_PROVIDERS.microsoft.services and matches microsoft-excel, microsoft-teams, microsoft-planner, microsoft-ad, and microsoft-dataverse by their providerId, returning 'microsoft'
  2. That feeds into the case 'microsoft': branch in getProviderAuthConfig, which now carries supportsRefreshTokenRotation: true

The four non-hyphenated IDs (outlook, onedrive, sharepoint) have their own explicit case labels in the same switch fall-through block, so they're covered directly without needing getBaseProviderForService.

The fd885f2 test extension covering all 9 service IDs end-to-end is a solid addition. The fix is correct and complete — good to merge.

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit fd885f2. Configure here.

@waleedlatif1 waleedlatif1 merged commit 3adbde4 into staging May 11, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/ms-oauth-refresh branch May 11, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant