@@ -786,30 +786,6 @@ describe('OAuth Authorization', () => {
786
786
expect ( calls [ 1 ] [ 0 ] . toString ( ) ) . toBe ( 'https://auth.example.com/.well-known/oauth-authorization-server' ) ;
787
787
} ) ;
788
788
789
- it ( 'throws error when OIDC provider does not support S256 PKCE' , async ( ) => {
790
- // OAuth discovery fails
791
- mockFetch . mockResolvedValueOnce ( {
792
- ok : false ,
793
- status : 404
794
- } ) ;
795
-
796
- // OpenID Connect discovery succeeds but without S256 support
797
- const invalidOpenIdMetadata = {
798
- ...validOpenIdMetadata ,
799
- code_challenge_methods_supported : [ 'plain' ] // Missing S256
800
- } ;
801
-
802
- mockFetch . mockResolvedValueOnce ( {
803
- ok : true ,
804
- status : 200 ,
805
- json : async ( ) => invalidOpenIdMetadata
806
- } ) ;
807
-
808
- await expect ( discoverAuthorizationServerMetadata ( 'https://auth.example.com' ) ) . rejects . toThrow (
809
- 'does not support S256 code challenge method required by MCP specification'
810
- ) ;
811
- } ) ;
812
-
813
789
it ( 'continues on 4xx errors' , async ( ) => {
814
790
mockFetch . mockResolvedValueOnce ( {
815
791
ok : false ,
@@ -913,6 +889,17 @@ describe('OAuth Authorization', () => {
913
889
code_challenge_methods_supported : [ 'S256' ]
914
890
} ;
915
891
892
+ const validOpenIdMetadata = {
893
+ issuer : 'https://auth.example.com' ,
894
+ authorization_endpoint : 'https://auth.example.com/auth' ,
895
+ token_endpoint : 'https://auth.example.com/token' ,
896
+ jwks_uri : 'https://auth.example.com/jwks' ,
897
+ subject_types_supported : [ 'public' ] ,
898
+ id_token_signing_alg_values_supported : [ 'RS256' ] ,
899
+ response_types_supported : [ 'code' ] ,
900
+ code_challenge_methods_supported : [ 'S256' ]
901
+ } ;
902
+
916
903
const validClientInfo = {
917
904
client_id : 'client123' ,
918
905
client_secret : 'secret123' ,
@@ -986,19 +973,19 @@ describe('OAuth Authorization', () => {
986
973
expect ( authorizationUrl . searchParams . get ( 'prompt' ) ) . toBe ( 'consent' ) ;
987
974
} ) ;
988
975
989
- it ( 'uses metadata authorization_endpoint when provided' , async ( ) => {
976
+ it . each ( [ validMetadata , validOpenIdMetadata ] ) ( 'uses metadata authorization_endpoint when provided' , async baseMetadata => {
990
977
const { authorizationUrl } = await startAuthorization ( 'https://auth.example.com' , {
991
- metadata : validMetadata ,
978
+ metadata : baseMetadata ,
992
979
clientInformation : validClientInfo ,
993
980
redirectUrl : 'http://localhost:3000/callback'
994
981
} ) ;
995
982
996
983
expect ( authorizationUrl . toString ( ) ) . toMatch ( / ^ h t t p s : \/ \/ a u t h \. e x a m p l e \. c o m \/ a u t h \? / ) ;
997
984
} ) ;
998
985
999
- it ( 'validates response type support' , async ( ) => {
986
+ it . each ( [ validMetadata , validOpenIdMetadata ] ) ( 'validates response type support' , async baseMetadata => {
1000
987
const metadata = {
1001
- ...validMetadata ,
988
+ ...baseMetadata ,
1002
989
response_types_supported : [ 'token' ] // Does not support 'code'
1003
990
} ;
1004
991
@@ -1011,21 +998,44 @@ describe('OAuth Authorization', () => {
1011
998
) . rejects . toThrow ( / d o e s n o t s u p p o r t r e s p o n s e t y p e / ) ;
1012
999
} ) ;
1013
1000
1014
- it ( 'validates PKCE support' , async ( ) => {
1015
- const metadata = {
1016
- ...validMetadata ,
1017
- response_types_supported : [ 'code' ] ,
1018
- code_challenge_methods_supported : [ 'plain' ] // Does not support 'S256'
1019
- } ;
1001
+ // https://github.com/modelcontextprotocol/typescript-sdk/issues/832
1002
+ it . each ( [ validMetadata , validOpenIdMetadata ] ) (
1003
+ 'assumes supported code challenge methods includes S256 if absent' ,
1004
+ async baseMetadata => {
1005
+ const metadata = {
1006
+ ...baseMetadata ,
1007
+ response_types_supported : [ 'code' ] ,
1008
+ code_challenge_methods_supported : undefined
1009
+ } ;
1020
1010
1021
- await expect (
1022
- startAuthorization ( 'https://auth.example.com' , {
1011
+ const { authorizationUrl } = await startAuthorization ( 'https://auth.example.com' , {
1023
1012
metadata,
1024
1013
clientInformation : validClientInfo ,
1025
1014
redirectUrl : 'http://localhost:3000/callback'
1026
- } )
1027
- ) . rejects . toThrow ( / d o e s n o t s u p p o r t c o d e c h a l l e n g e m e t h o d / ) ;
1028
- } ) ;
1015
+ } ) ;
1016
+
1017
+ expect ( authorizationUrl . toString ( ) ) . toMatch ( / ^ h t t p s : \/ \/ a u t h \. e x a m p l e \. c o m \/ a u t h \? .+ & c o d e _ c h a l l e n g e _ m e t h o d = S 2 5 6 / ) ;
1018
+ }
1019
+ ) ;
1020
+
1021
+ it . each ( [ validMetadata , validOpenIdMetadata ] ) (
1022
+ 'validates supported code challenge methods includes S256 if present' ,
1023
+ async baseMetadata => {
1024
+ const metadata = {
1025
+ ...baseMetadata ,
1026
+ response_types_supported : [ 'code' ] ,
1027
+ code_challenge_methods_supported : [ 'plain' ] // Does not support 'S256'
1028
+ } ;
1029
+
1030
+ await expect (
1031
+ startAuthorization ( 'https://auth.example.com' , {
1032
+ metadata,
1033
+ clientInformation : validClientInfo ,
1034
+ redirectUrl : 'http://localhost:3000/callback'
1035
+ } )
1036
+ ) . rejects . toThrow ( / d o e s n o t s u p p o r t c o d e c h a l l e n g e m e t h o d / ) ;
1037
+ }
1038
+ ) ;
1029
1039
} ) ;
1030
1040
1031
1041
describe ( 'exchangeAuthorization' , ( ) => {
0 commit comments