@@ -230,35 +230,59 @@ export function startMcpServer(config: McpServerConfig, port: number): void {
230230 }
231231
232232 if ( ! dashboardJwtSecret ) {
233- res . status ( 500 ) . json ( { error : "OAuth consent not configured" } ) ;
233+ console . error ( "[oauth] RM_DASHBOARD_JWT_SECRET not configured" ) ;
234+ res . status ( 500 ) . json ( { error : "OAuth consent not configured on server" } ) ;
234235 return ;
235236 }
236237
238+ // Step 1: Verify the JWT from the dashboard
239+ let payload : Record < string , unknown > ;
237240 try {
238241 const key = new TextEncoder ( ) . encode ( dashboardJwtSecret ) ;
239- const { payload } = await jwtVerify ( token , key , {
242+ const result = await jwtVerify ( token , key , {
240243 audience : "reflect-memory" ,
241244 issuer : "reflect-dashboard" ,
242245 } ) ;
246+ payload = result . payload as Record < string , unknown > ;
247+ } catch ( err ) {
248+ const msg = ( err as Error ) . message || String ( err ) ;
249+ console . error ( `[oauth] JWT verification failed: ${ msg } ` ) ;
250+ res . status ( 403 ) . json ( { error : "Token verification failed. Check that AUTH_SECRET and RM_DASHBOARD_JWT_SECRET match." } ) ;
251+ return ;
252+ }
243253
244- const pendingId = payload . pending_id as string ;
245- if ( ! pendingId ) {
246- res . status ( 400 ) . json ( { error : "Invalid approval token" } ) ;
247- return ;
248- }
254+ const pendingId = payload . pending_id as string ;
255+ if ( ! pendingId ) {
256+ res . status ( 400 ) . json ( { error : "Missing pending_id in approval token" } ) ;
257+ return ;
258+ }
249259
250- let approvedUserId : string | undefined ;
251- const email = payload . email as string | undefined ;
252- if ( email ) {
260+ // Step 2: Resolve the user from the email in the JWT (non-fatal if it fails)
261+ let approvedUserId : string | undefined ;
262+ const email = payload . email as string | undefined ;
263+ if ( email ) {
264+ try {
253265 approvedUserId = findOrCreateUserByEmail ( db , email ) ;
254266 console . log ( `[oauth] Resolved user ${ approvedUserId } from email ${ email } ` ) ;
267+ } catch ( err ) {
268+ console . error ( `[oauth] User resolution failed for ${ email } : ${ ( err as Error ) . message } ` ) ;
255269 }
270+ }
256271
272+ // Step 3: Approve the pending request and redirect
273+ try {
257274 const redirectUrl = oauthProvider . approvePendingRequest ( pendingId , approvedUserId ) ;
258275 res . redirect ( 302 , redirectUrl ) ;
259276 } catch ( err ) {
260- console . error ( "[oauth] Approval failed:" , ( err as Error ) . message ) ;
261- res . status ( 403 ) . json ( { error : "Invalid or expired approval" } ) ;
277+ const msg = ( err as Error ) . message || String ( err ) ;
278+ console . error ( `[oauth] Pending request approval failed: ${ msg } ` ) ;
279+ if ( msg . includes ( "expired" ) ) {
280+ res . status ( 410 ) . json ( { error : "Authorization request expired. Go back to your AI tool and try connecting again." } ) ;
281+ } else if ( msg . includes ( "not found" ) ) {
282+ res . status ( 404 ) . json ( { error : "Authorization request not found. It may have been used already. Try connecting again." } ) ;
283+ } else {
284+ res . status ( 500 ) . json ( { error : `Approval failed: ${ msg } ` } ) ;
285+ }
262286 }
263287 } ) ;
264288
@@ -490,7 +514,18 @@ export function startMcpServer(config: McpServerConfig, port: number): void {
490514 } ) ;
491515
492516 app . get ( "/health" , ( _req , res ) => {
493- res . json ( { service : "reflect-memory-mcp" , status : "ok" } ) ;
517+ const secretLen = dashboardJwtSecret ?. length ?? 0 ;
518+ res . json ( {
519+ service : "reflect-memory-mcp" ,
520+ status : "ok" ,
521+ oauth : {
522+ jwt_secret_configured : secretLen > 0 ,
523+ jwt_secret_length : secretLen ,
524+ dashboard_url : dashboardUrl || "(not set)" ,
525+ public_url : publicUrl || "(not set)" ,
526+ } ,
527+ sessions : Object . keys ( transports ) . length ,
528+ } ) ;
494529 } ) ;
495530
496531 const vendors = Object . keys ( agentKeys ) ;
0 commit comments