1- import { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js" ;
1+ import { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js" ;
22import {
33 InvalidTokenError ,
44 InsufficientScopeError ,
55 ServerError ,
66} from "@modelcontextprotocol/sdk/server/auth/errors.js" ;
7- import { withAuthContext } from "./auth-context" ;
7+ import { withAuthContext } from "./auth-context" ;
88
99declare global {
1010 interface Request {
@@ -29,16 +29,32 @@ export function withMcpAuth(
2929 } = { }
3030) {
3131 return async ( req : Request ) => {
32- try {
33- const authHeader = req . headers . get ( "Authorization" ) ;
34- const [ type , token ] = authHeader ?. split ( " " ) || [ ] ;
32+ const origin = new URL ( req . url ) . origin ;
33+ const resourceMetadataUrl = `${ origin } ${ resourceMetadataPath } ` ;
3534
36- // Only support bearer token as per the MCP spec
37- // https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#2-6-1-token-requirements
38- const bearerToken = type ?. toLowerCase ( ) === "bearer" ? token : undefined ;
35+ const authHeader = req . headers . get ( "Authorization" ) ;
36+ const [ type , token ] = authHeader ?. split ( " " ) || [ ] ;
3937
40- const authInfo = await verifyToken ( req , bearerToken ) ;
38+ // Only support bearer token as per the MCP spec
39+ // https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization#2-6-1-token-requirements
40+ const bearerToken = type ?. toLowerCase ( ) === "bearer" ? token : undefined ;
4141
42+ let authInfo : AuthInfo | undefined ;
43+ try {
44+ authInfo = await verifyToken ( req , bearerToken ) ;
45+ } catch ( error ) {
46+ console . error ( "Unexpected error authenticating bearer token:" , error ) ;
47+ const publicError = new InvalidTokenError ( "Invalid token" ) ;
48+ return new Response ( JSON . stringify ( publicError . toResponseObject ( ) ) , {
49+ status : 401 ,
50+ headers : {
51+ "WWW-Authenticate" : `Bearer error="${ publicError . errorCode } ", error_description="${ publicError . message } ", resource_metadata="${ resourceMetadataUrl } "` ,
52+ "Content-Type" : "application/json" ,
53+ } ,
54+ } ) ;
55+ }
56+
57+ try {
4258 if ( required && ! authInfo ) {
4359 throw new InvalidTokenError ( "No authorization provided" ) ;
4460 }
@@ -50,7 +66,7 @@ export function withMcpAuth(
5066 // Check if token has the required scopes (if any)
5167 if ( requiredScopes ?. length ) {
5268 const hasAllScopes = requiredScopes . every ( ( scope ) =>
53- authInfo . scopes . includes ( scope )
69+ authInfo ! . scopes . includes ( scope )
5470 ) ;
5571
5672 if ( ! hasAllScopes ) {
@@ -68,9 +84,6 @@ export function withMcpAuth(
6884
6985 return withAuthContext ( authInfo , ( ) => handler ( req ) ) ;
7086 } catch ( error ) {
71- const origin = new URL ( req . url ) . origin ;
72- const resourceMetadataUrl = `${ origin } ${ resourceMetadataPath } ` ;
73-
7487 if ( error instanceof InvalidTokenError ) {
7588 return new Response ( JSON . stringify ( error . toResponseObject ( ) ) , {
7689 status : 401 ,
0 commit comments