@@ -14,7 +14,7 @@ import {
1414 selectClientAuthMethod
1515} from './auth.js' ;
1616import { ServerError } from '../server/auth/errors.js' ;
17- import { AuthorizationServerMetadata } from '../shared/auth.js' ;
17+ import { AuthorizationServerMetadata , OAuthTokens } from '../shared/auth.js' ;
1818
1919// Mock fetch globally
2020const mockFetch = jest . fn ( ) ;
@@ -1073,7 +1073,7 @@ describe('OAuth Authorization', () => {
10731073 } ) ;
10741074
10751075 describe ( 'exchangeAuthorization' , ( ) => {
1076- const validTokens = {
1076+ const validTokens : OAuthTokens = {
10771077 access_token : 'access123' ,
10781078 token_type : 'Bearer' ,
10791079 expires_in : 3600 ,
@@ -1132,6 +1132,43 @@ describe('OAuth Authorization', () => {
11321132 expect ( body . get ( 'resource' ) ) . toBe ( 'https://api.example.com/mcp-server' ) ;
11331133 } ) ;
11341134
1135+ it ( 'allows for string "expires_in" values' , async ( ) => {
1136+ mockFetch . mockResolvedValueOnce ( {
1137+ ok : true ,
1138+ status : 200 ,
1139+ json : async ( ) => ( { ...validTokens , expires_in : '3600' } )
1140+ } ) ;
1141+
1142+ const tokens = await exchangeAuthorization ( 'https://auth.example.com' , {
1143+ clientInformation : validClientInfo ,
1144+ authorizationCode : 'code123' ,
1145+ codeVerifier : 'verifier123' ,
1146+ redirectUri : 'http://localhost:3000/callback' ,
1147+ resource : new URL ( 'https://api.example.com/mcp-server' )
1148+ } ) ;
1149+
1150+ expect ( tokens ) . toEqual ( validTokens ) ;
1151+ expect ( mockFetch ) . toHaveBeenCalledWith (
1152+ expect . objectContaining ( {
1153+ href : 'https://auth.example.com/token'
1154+ } ) ,
1155+ expect . objectContaining ( {
1156+ method : 'POST' ,
1157+ headers : new Headers ( {
1158+ 'Content-Type' : 'application/x-www-form-urlencoded'
1159+ } )
1160+ } )
1161+ ) ;
1162+
1163+ const body = mockFetch . mock . calls [ 0 ] [ 1 ] . body as URLSearchParams ;
1164+ expect ( body . get ( 'grant_type' ) ) . toBe ( 'authorization_code' ) ;
1165+ expect ( body . get ( 'code' ) ) . toBe ( 'code123' ) ;
1166+ expect ( body . get ( 'code_verifier' ) ) . toBe ( 'verifier123' ) ;
1167+ expect ( body . get ( 'client_id' ) ) . toBe ( 'client123' ) ;
1168+ expect ( body . get ( 'client_secret' ) ) . toBe ( 'secret123' ) ;
1169+ expect ( body . get ( 'redirect_uri' ) ) . toBe ( 'http://localhost:3000/callback' ) ;
1170+ expect ( body . get ( 'resource' ) ) . toBe ( 'https://api.example.com/mcp-server' ) ;
1171+ } ) ;
11351172 it ( 'exchanges code for tokens with auth' , async ( ) => {
11361173 mockFetch . mockResolvedValueOnce ( {
11371174 ok : true ,
0 commit comments