@@ -5,6 +5,43 @@ import { test, expect, inject } from 'vitest'
55const mcpServerPort = inject ( 'mcpServerPort' )
66const EPIC_ME_SERVER_URL = 'http://localhost:7788'
77
8+ // TypeScript interfaces for API responses
9+ interface AuthServerConfig {
10+ authorization_endpoint : string
11+ token_endpoint : string
12+ [ key : string ] : unknown
13+ }
14+
15+ interface ProtectedResourceConfig {
16+ resource : string
17+ scopes : string [ ]
18+ [ key : string ] : unknown
19+ }
20+
21+ interface ClientRegistration {
22+ client_id : string
23+ client_secret ?: string
24+ [ key : string ] : unknown
25+ }
26+
27+ interface AuthResult {
28+ redirectTo : string
29+ [ key : string ] : unknown
30+ }
31+
32+ interface TokenResult {
33+ access_token : string
34+ token_type : string
35+ [ key : string ] : unknown
36+ }
37+
38+ interface OriginalParams {
39+ client_id : string
40+ redirect_uri : string
41+ response_type : string
42+ [ key : string ] : unknown
43+ }
44+
845// Helper function to generate PKCE challenge
946function generateCodeChallenge ( ) {
1047 const codeVerifier = btoa (
@@ -46,21 +83,22 @@ test('OAuth integration flow works end-to-end', async () => {
4683 const authUrlMatch = wwwAuthHeader ?. match ( / a u t h o r i z a t i o n _ u r l = " ( [ ^ " ] + ) " / )
4784 expect ( authUrlMatch , '🚨 Could not extract authorization URL from WWW-Authenticate header' ) . toBeTruthy ( )
4885 const authorizationUrl = authUrlMatch ! [ 1 ]
86+ expect ( authorizationUrl , '🚨 Authorization URL should not be empty' ) . toBeTruthy ( )
4987
5088 // Step 1: Metadata discovery
5189 // Test OAuth Authorization Server discovery
5290 const authServerDiscoveryResponse = await fetch ( `${ mcpServerUrl } /.well-known/oauth-authorization-server` )
5391 expect ( authServerDiscoveryResponse . ok , '🚨 OAuth authorization server discovery should succeed' ) . toBe ( true )
5492
55- const authServerConfig = await authServerDiscoveryResponse . json ( )
93+ const authServerConfig = await authServerDiscoveryResponse . json ( ) as AuthServerConfig
5694 expect ( authServerConfig . authorization_endpoint , '🚨 Authorization endpoint should be present in discovery' ) . toBeTruthy ( )
5795 expect ( authServerConfig . token_endpoint , '🚨 Token endpoint should be present in discovery' ) . toBeTruthy ( )
5896
5997 // Test OAuth Protected Resource discovery
6098 const protectedResourceDiscoveryResponse = await fetch ( `${ mcpServerUrl } /.well-known/oauth-protected-resource/mcp` )
6199 expect ( protectedResourceDiscoveryResponse . ok , '🚨 OAuth protected resource discovery should succeed' ) . toBe ( true )
62100
63- const protectedResourceConfig = await protectedResourceDiscoveryResponse . json ( )
101+ const protectedResourceConfig = await protectedResourceDiscoveryResponse . json ( ) as ProtectedResourceConfig
64102 expect ( protectedResourceConfig . resource , '🚨 Resource identifier should be present' ) . toBe ( 'epicme-mcp' )
65103 expect ( protectedResourceConfig . scopes , '🚨 Scopes should be present' ) . toContain ( 'read' )
66104 expect ( protectedResourceConfig . scopes , '🚨 Scopes should contain write' ) . toContain ( 'write' )
@@ -77,16 +115,16 @@ test('OAuth integration flow works end-to-end', async () => {
77115 } )
78116
79117 expect ( clientRegistrationResponse . ok , '🚨 Client registration should succeed' ) . toBe ( true )
80- const clientRegistration = await clientRegistrationResponse . json ( )
118+ const clientRegistration = await clientRegistrationResponse . json ( ) as ClientRegistration
81119 expect ( clientRegistration . client_id , '🚨 Client ID should be returned from registration' ) . toBeTruthy ( )
82120
83121 // Step 3: Preparing Authorization (getting the auth URL)
84122 const { codeVerifier, codeChallenge, codeChallengeMethod } = generateCodeChallenge ( )
85123 const state = crypto . randomUUID ( )
86124 const redirectUri = `${ mcpServerUrl } /mcp`
87125
88- const authUrl = new URL ( authorizationUrl )
89- const originalParams = JSON . parse ( authUrl . searchParams . get ( 'oauth_req_info' ) || '{}' )
126+ const authUrl = new URL ( authorizationUrl as string )
127+ const originalParams = JSON . parse ( authUrl . searchParams . get ( 'oauth_req_info' ) || '{}' ) as OriginalParams
90128
91129 expect ( originalParams . client_id , '🚨 Client ID should be present in auth URL' ) . toBeTruthy ( )
92130 expect ( originalParams . redirect_uri , '🚨 Redirect URI should be present in auth URL' ) . toBeTruthy ( )
@@ -106,7 +144,7 @@ test('OAuth integration flow works end-to-end', async () => {
106144 const authCodeResponse = await fetch ( testAuthUrl . toString ( ) )
107145 expect ( authCodeResponse . ok , '🚨 Auth code request should succeed' ) . toBe ( true )
108146
109- const authResult = await authCodeResponse . json ( )
147+ const authResult = await authCodeResponse . json ( ) as AuthResult
110148 expect ( authResult . redirectTo , '🚨 Redirect URL should be returned' ) . toBeTruthy ( )
111149
112150 // Step 5: Supplying the auth code (extract from redirect URL)
@@ -143,7 +181,7 @@ test('OAuth integration flow works end-to-end', async () => {
143181 }
144182
145183 expect ( tokenResponse . ok , '🚨 Token exchange should succeed' ) . toBe ( true )
146- const tokenResult = await tokenResponse . json ( )
184+ const tokenResult = await tokenResponse . json ( ) as TokenResult
147185 expect ( tokenResult . access_token , '🚨 Access token should be returned' ) . toBeTruthy ( )
148186 expect ( tokenResult . token_type ?. toLowerCase ( ) , '🚨 Token type should be Bearer' ) . toBe ( 'bearer' )
149187
0 commit comments