@@ -2,8 +2,18 @@ import { useEffect, useRef } from "react";
22import { InspectorOAuthClientProvider } from "../lib/auth" ;
33import { SESSION_KEYS } from "../lib/constants" ;
44import { auth } from "@modelcontextprotocol/sdk/client/auth.js" ;
5+ import { useToast } from "@/hooks/use-toast.ts" ;
6+ import {
7+ generateOAuthErrorDescription ,
8+ parseOAuthCallbackParams ,
9+ } from "@/utils/oauthUtils.ts" ;
510
6- const OAuthCallback = ( ) => {
11+ interface OAuthCallbackProps {
12+ onConnect : ( serverUrl : string ) => void ;
13+ }
14+
15+ const OAuthCallback = ( { onConnect } : OAuthCallbackProps ) => {
16+ const { toast } = useToast ( ) ;
717 const hasProcessedRef = useRef ( false ) ;
818
919 useEffect ( ( ) => {
@@ -14,40 +24,56 @@ const OAuthCallback = () => {
1424 }
1525 hasProcessedRef . current = true ;
1626
17- const params = new URLSearchParams ( window . location . search ) ;
18- const code = params . get ( "code" ) ;
19- const serverUrl = sessionStorage . getItem ( SESSION_KEYS . SERVER_URL ) ;
27+ const notifyError = ( description : string ) =>
28+ void toast ( {
29+ title : "OAuth Authorization Error" ,
30+ description,
31+ variant : "destructive" ,
32+ } ) ;
2033
21- if ( ! code || ! serverUrl ) {
22- console . error ( "Missing code or server URL" ) ;
23- window . location . href = "/" ;
24- return ;
34+ const params = parseOAuthCallbackParams ( window . location . search ) ;
35+ if ( ! params . successful ) {
36+ return notifyError ( generateOAuthErrorDescription ( params ) ) ;
37+ }
38+
39+ const serverUrl = sessionStorage . getItem ( SESSION_KEYS . SERVER_URL ) ;
40+ if ( ! serverUrl ) {
41+ return notifyError ( "Missing Server URL" ) ;
2542 }
2643
44+ let result ;
2745 try {
2846 // Create an auth provider with the current server URL
2947 const serverAuthProvider = new InspectorOAuthClientProvider ( serverUrl ) ;
3048
31- const result = await auth ( serverAuthProvider , {
49+ result = await auth ( serverAuthProvider , {
3250 serverUrl,
33- authorizationCode : code ,
51+ authorizationCode : params . code ,
3452 } ) ;
35- if ( result !== "AUTHORIZED" ) {
36- throw new Error (
37- `Expected to be authorized after providing auth code, got: ${ result } ` ,
38- ) ;
39- }
40-
41- // Redirect back to the main app with server URL to trigger auto-connect
42- window . location . href = `/?serverUrl=${ encodeURIComponent ( serverUrl ) } ` ;
4353 } catch ( error ) {
4454 console . error ( "OAuth callback error:" , error ) ;
45- window . location . href = "/" ;
55+ return notifyError ( `Unexpected error occurred: ${ error } ` ) ;
4656 }
57+
58+ if ( result !== "AUTHORIZED" ) {
59+ return notifyError (
60+ `Expected to be authorized after providing auth code, got: ${ result } ` ,
61+ ) ;
62+ }
63+
64+ // Finally, trigger auto-connect
65+ toast ( {
66+ title : "Success" ,
67+ description : "Successfully authenticated with OAuth" ,
68+ variant : "default" ,
69+ } ) ;
70+ onConnect ( serverUrl ) ;
4771 } ;
4872
49- void handleCallback ( ) ;
50- } , [ ] ) ;
73+ handleCallback ( ) . finally ( ( ) => {
74+ window . history . replaceState ( { } , document . title , "/" ) ;
75+ } ) ;
76+ } , [ toast , onConnect ] ) ;
5177
5278 return (
5379 < div className = "flex items-center justify-center h-screen" >
0 commit comments