1
+ import { IncomingMessage } from "http" ;
2
+ import { describe , expect , it } from "vitest" ;
3
+
4
+ import { AuthenticationMiddleware } from "./authentication.js" ;
5
+
6
+ describe ( "AuthenticationMiddleware" , ( ) => {
7
+ const createMockRequest = ( headers : Record < string , string > = { } ) : IncomingMessage => {
8
+ // Simulate Node.js http module behavior which converts all header names to lowercase
9
+ const lowercaseHeaders : Record < string , string > = { } ;
10
+ for ( const [ key , value ] of Object . entries ( headers ) ) {
11
+ lowercaseHeaders [ key . toLowerCase ( ) ] = value ;
12
+ }
13
+ return {
14
+ headers : lowercaseHeaders ,
15
+ } as IncomingMessage ;
16
+ } ;
17
+
18
+ describe ( "when no auth is configured" , ( ) => {
19
+ it ( "should allow all requests" , ( ) => {
20
+ const middleware = new AuthenticationMiddleware ( { } ) ;
21
+ const req = createMockRequest ( ) ;
22
+
23
+ expect ( middleware . validateRequest ( req ) ) . toBe ( true ) ;
24
+ } ) ;
25
+
26
+ it ( "should allow requests even with headers" , ( ) => {
27
+ const middleware = new AuthenticationMiddleware ( { } ) ;
28
+ const req = createMockRequest ( { "x-api-key" : "some-key" } ) ;
29
+
30
+ expect ( middleware . validateRequest ( req ) ) . toBe ( true ) ;
31
+ } ) ;
32
+ } ) ;
33
+
34
+ describe ( "X-API-Key validation" , ( ) => {
35
+ const apiKey = "test-api-key-123" ;
36
+
37
+ it ( "should accept valid API key" , ( ) => {
38
+ const middleware = new AuthenticationMiddleware ( { apiKey } ) ;
39
+ const req = createMockRequest ( { "x-api-key" : apiKey } ) ;
40
+
41
+ expect ( middleware . validateRequest ( req ) ) . toBe ( true ) ;
42
+ } ) ;
43
+
44
+ it ( "should reject missing API key" , ( ) => {
45
+ const middleware = new AuthenticationMiddleware ( { apiKey } ) ;
46
+ const req = createMockRequest ( ) ;
47
+
48
+ expect ( middleware . validateRequest ( req ) ) . toBe ( false ) ;
49
+ } ) ;
50
+
51
+ it ( "should reject incorrect API key" , ( ) => {
52
+ const middleware = new AuthenticationMiddleware ( { apiKey } ) ;
53
+ const req = createMockRequest ( { "x-api-key" : "wrong-key" } ) ;
54
+
55
+ expect ( middleware . validateRequest ( req ) ) . toBe ( false ) ;
56
+ } ) ;
57
+
58
+ it ( "should reject empty API key" , ( ) => {
59
+ const middleware = new AuthenticationMiddleware ( { apiKey } ) ;
60
+ const req = createMockRequest ( { "x-api-key" : "" } ) ;
61
+
62
+ expect ( middleware . validateRequest ( req ) ) . toBe ( false ) ;
63
+ } ) ;
64
+
65
+ it ( "should be case-insensitive for header names" , ( ) => {
66
+ const middleware = new AuthenticationMiddleware ( { apiKey } ) ;
67
+ const req = createMockRequest ( { "X-API-KEY" : apiKey } ) ;
68
+
69
+ expect ( middleware . validateRequest ( req ) ) . toBe ( true ) ;
70
+ } ) ;
71
+
72
+ it ( "should work with mixed case header names" , ( ) => {
73
+ const middleware = new AuthenticationMiddleware ( { apiKey } ) ;
74
+ const req = createMockRequest ( { "X-Api-Key" : apiKey } ) ;
75
+
76
+ expect ( middleware . validateRequest ( req ) ) . toBe ( true ) ;
77
+ } ) ;
78
+
79
+ it ( "should handle array headers (if multiple same headers)" , ( ) => {
80
+ const middleware = new AuthenticationMiddleware ( { apiKey } ) ;
81
+ const req = {
82
+ headers : {
83
+ "x-api-key" : [ apiKey , "another-key" ] ,
84
+ } ,
85
+ } as unknown as IncomingMessage ;
86
+
87
+ // Should fail because header is an array, not a string
88
+ expect ( middleware . validateRequest ( req ) ) . toBe ( false ) ;
89
+ } ) ;
90
+ } ) ;
91
+
92
+ describe ( "getUnauthorizedResponse" , ( ) => {
93
+ it ( "should return proper unauthorized response" , ( ) => {
94
+ const middleware = new AuthenticationMiddleware ( { apiKey : "test" } ) ;
95
+ const response = middleware . getUnauthorizedResponse ( ) ;
96
+
97
+ expect ( response . headers [ "Content-Type" ] ) . toBe ( "application/json" ) ;
98
+
99
+ const body = JSON . parse ( response . body ) ;
100
+ expect ( body . error . code ) . toBe ( 401 ) ;
101
+ expect ( body . error . message ) . toBe ( "Unauthorized: Invalid or missing API key" ) ;
102
+ expect ( body . jsonrpc ) . toBe ( "2.0" ) ;
103
+ expect ( body . id ) . toBe ( null ) ;
104
+ } ) ;
105
+
106
+ it ( "should have consistent format regardless of configuration" , ( ) => {
107
+ const middleware1 = new AuthenticationMiddleware ( { } ) ;
108
+ const middleware2 = new AuthenticationMiddleware ( { apiKey : "test" } ) ;
109
+
110
+ const response1 = middleware1 . getUnauthorizedResponse ( ) ;
111
+ const response2 = middleware2 . getUnauthorizedResponse ( ) ;
112
+
113
+ expect ( response1 . headers ) . toEqual ( response2 . headers ) ;
114
+ expect ( response1 . body ) . toEqual ( response2 . body ) ;
115
+ } ) ;
116
+ } ) ;
117
+ } ) ;
0 commit comments