fix: add scope to Microsoft OAuth callback#1508
Conversation
…hange Co-authored-by: Konsti <n2d4xc@gmail.com>
|
Requesting review from @N2D4 who has experience with the following files modified in this PR:
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
Greptile SummaryFixes the
Confidence Score: 4/5Safe to merge; the change is narrowly scoped to Microsoft and leaves all other providers' token exchange behavior unchanged. The implementation is clean and well-isolated. apps/backend/src/oauth/providers/base.test.ts — the no-extra-scope case for Important Files Changed
Sequence DiagramsequenceDiagram
participant Browser
participant CallbackRoute as OAuth Callback Route
participant MicrosoftProvider
participant getOAuthCallbackExtras
participant MSTokenEndpoint as Microsoft Token Endpoint
Browser->>CallbackRoute: "GET /callback/microsoft?code=..."
CallbackRoute->>CallbackRoute: Read providerScope from OAuthOuterInfo
CallbackRoute->>MicrosoftProvider: "getCallback({ extraScope: providerScope, ... })"
MicrosoftProvider->>getOAuthCallbackExtras: "{ baseScope, extraScope, includeScopeInCallbackTokenRequest: true }"
getOAuthCallbackExtras-->>MicrosoftProvider: "{ exchangeBody: { scope: "User.Read openid [extra]" } }"
MicrosoftProvider->>MSTokenEndpoint: "POST /token (code + scope=...)"
MSTokenEndpoint-->>MicrosoftProvider: access_token + id_token
MicrosoftProvider-->>CallbackRoute: "{ userInfo, tokenSet }"
CallbackRoute-->>Browser: Redirect with session
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
apps/backend/src/oauth/providers/base.test.ts:113-124
Missing test for the common case where a Microsoft user has no extra scopes. When `includeScopeInCallbackTokenRequest` is `true` but `extraScope` is absent, the function should still return `exchangeBody.scope` containing just the base scope. Without this test, a future refactor of the `extraScope || ""` fallback could silently drop the scope from the token exchange body in the default (no extra scopes) flow.
```suggestion
it("adds the merged scope to callback token exchange extras when enabled", () => {
expect(getOAuthCallbackExtras({
baseScope: "User.Read openid",
extraScope: "Mail.Read User.Read",
includeScopeInCallbackTokenRequest: true,
})).toEqual({
exchangeBody: {
scope: "User.Read openid Mail.Read",
},
});
});
it("uses only baseScope when no extraScope is provided and includeScopeInCallbackTokenRequest is true", () => {
expect(getOAuthCallbackExtras({
baseScope: "User.Read openid",
includeScopeInCallbackTokenRequest: true,
})).toEqual({
exchangeBody: {
scope: "User.Read openid",
},
});
});
});
```
Reviews (1): Last reviewed commit: "fix(oauth): include scope param in Micro..." | Re-trigger Greptile |
| it("adds the merged scope to callback token exchange extras when enabled", () => { | ||
| expect(getOAuthCallbackExtras({ | ||
| baseScope: "User.Read openid", | ||
| extraScope: "Mail.Read User.Read", | ||
| includeScopeInCallbackTokenRequest: true, | ||
| })).toEqual({ | ||
| exchangeBody: { | ||
| scope: "User.Read openid Mail.Read", | ||
| }, | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Missing test for the common case where a Microsoft user has no extra scopes. When
includeScopeInCallbackTokenRequest is true but extraScope is absent, the function should still return exchangeBody.scope containing just the base scope. Without this test, a future refactor of the extraScope || "" fallback could silently drop the scope from the token exchange body in the default (no extra scopes) flow.
| it("adds the merged scope to callback token exchange extras when enabled", () => { | |
| expect(getOAuthCallbackExtras({ | |
| baseScope: "User.Read openid", | |
| extraScope: "Mail.Read User.Read", | |
| includeScopeInCallbackTokenRequest: true, | |
| })).toEqual({ | |
| exchangeBody: { | |
| scope: "User.Read openid Mail.Read", | |
| }, | |
| }); | |
| }); | |
| }); | |
| it("adds the merged scope to callback token exchange extras when enabled", () => { | |
| expect(getOAuthCallbackExtras({ | |
| baseScope: "User.Read openid", | |
| extraScope: "Mail.Read User.Read", | |
| includeScopeInCallbackTokenRequest: true, | |
| })).toEqual({ | |
| exchangeBody: { | |
| scope: "User.Read openid Mail.Read", | |
| }, | |
| }); | |
| }); | |
| it("uses only baseScope when no extraScope is provided and includeScopeInCallbackTokenRequest is true", () => { | |
| expect(getOAuthCallbackExtras({ | |
| baseScope: "User.Read openid", | |
| includeScopeInCallbackTokenRequest: true, | |
| })).toEqual({ | |
| exchangeBody: { | |
| scope: "User.Read openid", | |
| }, | |
| }); | |
| }); | |
| }); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/backend/src/oauth/providers/base.test.ts
Line: 113-124
Comment:
Missing test for the common case where a Microsoft user has no extra scopes. When `includeScopeInCallbackTokenRequest` is `true` but `extraScope` is absent, the function should still return `exchangeBody.scope` containing just the base scope. Without this test, a future refactor of the `extraScope || ""` fallback could silently drop the scope from the token exchange body in the default (no extra scopes) flow.
```suggestion
it("adds the merged scope to callback token exchange extras when enabled", () => {
expect(getOAuthCallbackExtras({
baseScope: "User.Read openid",
extraScope: "Mail.Read User.Read",
includeScopeInCallbackTokenRequest: true,
})).toEqual({
exchangeBody: {
scope: "User.Read openid Mail.Read",
},
});
});
it("uses only baseScope when no extraScope is provided and includeScopeInCallbackTokenRequest is true", () => {
expect(getOAuthCallbackExtras({
baseScope: "User.Read openid",
includeScopeInCallbackTokenRequest: true,
})).toEqual({
exchangeBody: {
scope: "User.Read openid",
},
});
});
});
```
How can I resolve this? If you propose a fix, please make it concise.
Summary
Add support for including the 'scope' parameter in Microsoft OAuth callback token exchange to fix invalid_scope error.
providerScopeasextraScopetogetCallbackin OAuth callback handler.getOAuthCallbackExtrasto conditionally add merged scopes to token exchange request.includeScopeInCallbackTokenRequestflag in Microsoft provider to include scope in token exchange.getOAuthCallbackExtrasbehavior.This resolves the AADSTS70011 error caused by missing 'scope' in token exchange request for Microsoft OAuth.
Summary by cubic
Fix Microsoft OAuth invalid_scope (AADSTS70011) by sending the merged scope in the callback token exchange. Scoped to Microsoft only; other providers are unchanged.
providerScopeasextraScopetogetCallbackin the OAuth callback.getOAuthCallbackExtrasto merge scopes and include them in the token exchange when enabled.includeScopeInCallbackTokenRequest: truefor the Microsoft provider.getOAuthCallbackExtras.Written for commit 24f28da. Summary will update on new commits.
Review in cubic