Skip to content

Commit a30fcbb

Browse files
fix(web): handle duplicate resource query params in OAuth authorize endpoint (#987)
* fix(web): handle duplicate resource query params in OAuth authorize endpoint RFC 8707 allows multiple resource parameters in authorization requests. Sourcebot only supports a single resource (the MCP endpoint), so deduplicate by taking the first value. Also improves error handling in the consent screen to show a toast when authorization fails. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: update CHANGELOG for #987 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1582483 commit a30fcbb

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
- [EE] Handle duplicate `resource` query parameters in the OAuth authorization endpoint. [#987](https://github.com/sourcebot-dev/sourcebot/pull/987)
12+
1013
## [4.15.2] - 2026-03-06
1114

1215
### Fixed

packages/web/src/app/oauth/authorize/components/consentScreen.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Image from 'next/image';
88
import logo from '@/public/logo_512.png';
99
import { useEffect, useState } from 'react';
1010
import useCaptureEvent from '@/hooks/useCaptureEvent';
11+
import { useToast } from '@/components/hooks/use-toast';
1112

1213
interface ConsentScreenProps {
1314
clientId: string;
@@ -32,6 +33,7 @@ export function ConsentScreen({
3233
}: ConsentScreenProps) {
3334
const [pending, setPending] = useState<'approve' | 'deny' | null>(null);
3435
const captureEvent = useCaptureEvent();
36+
const { toast } = useToast();
3537

3638
useEffect(() => {
3739
captureEvent('wa_oauth_consent_viewed', { clientId, clientName });
@@ -41,11 +43,17 @@ export function ConsentScreen({
4143
captureEvent('wa_oauth_authorization_approved', { clientId, clientName });
4244
setPending('approve');
4345
const result = await approveAuthorization({ clientId, redirectUri, codeChallenge, resource, state });
44-
if (isServiceError(result)) {
45-
setPending(null);
46-
return;
46+
if (!isServiceError(result)) {
47+
window.location.href = result;
48+
toast({
49+
description: `✅ Authorization approved successfully. Redirecting to ${result}...`,
50+
});
51+
} else {
52+
toast({
53+
description: `❌ Failed to approve authorization. ${result.message}`,
54+
});
4755
}
48-
window.location.href = result;
56+
setPending(null);
4957
};
5058

5159
const onDeny = async () => {

packages/web/src/app/oauth/authorize/page.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface AuthorizePageProps {
1515
code_challenge_method?: string;
1616
response_type?: string;
1717
state?: string;
18-
resource?: string;
18+
resource?: string | string[];
1919
}>;
2020
}
2121

@@ -25,7 +25,13 @@ export default async function AuthorizePage({ searchParams }: AuthorizePageProps
2525
}
2626

2727
const params = await searchParams;
28-
const { client_id, redirect_uri, code_challenge, code_challenge_method, response_type, state, resource } = params;
28+
const { client_id, redirect_uri, code_challenge, code_challenge_method, response_type, state, resource: _resource } = params;
29+
30+
// RFC 8707 allows multiple resource parameters to indicate a token intended for multiple resources.
31+
// Sourcebot only supports a single resource (the MCP endpoint), so we take the first value.
32+
//
33+
// @see: https://www.rfc-editor.org/rfc/rfc8707.html#section-2-2.2
34+
const resource = Array.isArray(_resource) ? _resource[0] : _resource;
2935

3036
// Validate required parameters. Per spec, do NOT redirect on client errors —
3137
// show an error page instead to avoid open redirect vulnerabilities.

0 commit comments

Comments
 (0)