@@ -40,11 +40,102 @@ describe("auth", () => {
4040 testCases . forEach ( testCase => {
4141 it ( `${ testCase . resourceMetadata } → ${ testCase . resource } ` , async ( ) => {
4242 const req = new Request ( testCase . resourceMetadata ) ;
43- const res = handler ( req ) ;
43+ const res = handler ( req ) ;
4444 const json = await res . json ( ) ;
4545 expect ( json . resource ) . toBe ( testCase . resource ) ;
4646 } ) ;
4747 } ) ;
4848 } ) ;
49+
50+ describe ( "proxy header support" , ( ) => {
51+ const handler = protectedResourceHandler ( {
52+ authServerUrls : [ "https://auth-server.com" ] ,
53+ } ) ;
54+
55+ it ( "uses X-Forwarded-Host and X-Forwarded-Proto headers" , async ( ) => {
56+ const req = new Request ( "http://localhost:3000/.well-known/oauth-protected-resource" , {
57+ headers : {
58+ "X-Forwarded-Host" : "example.org" ,
59+ "X-Forwarded-Proto" : "https" ,
60+ } ,
61+ } ) ;
62+ const res = handler ( req ) ;
63+ const json = await res . json ( ) ;
64+ expect ( json . resource ) . toBe ( "https://example.org" ) ;
65+ } ) ;
66+
67+ it ( "handles X-Forwarded-Host with multiple values (uses first)" , async ( ) => {
68+ const req = new Request ( "http://localhost:3000/.well-known/oauth-protected-resource" , {
69+ headers : {
70+ "X-Forwarded-Host" : "example.org, proxy1.internal, proxy2.internal" ,
71+ "X-Forwarded-Proto" : "https" ,
72+ } ,
73+ } ) ;
74+ const res = handler ( req ) ;
75+ const json = await res . json ( ) ;
76+ expect ( json . resource ) . toBe ( "https://example.org" ) ;
77+ } ) ;
78+
79+ it ( "defaults to https when X-Forwarded-Proto is missing" , async ( ) => {
80+ const req = new Request ( "http://localhost:3000/.well-known/oauth-protected-resource" , {
81+ headers : {
82+ "X-Forwarded-Host" : "example.org" ,
83+ } ,
84+ } ) ;
85+ const res = handler ( req ) ;
86+ const json = await res . json ( ) ;
87+ expect ( json . resource ) . toBe ( "https://example.org" ) ;
88+ } ) ;
89+
90+ it ( "uses RFC 7239 Forwarded header" , async ( ) => {
91+ const req = new Request ( "http://localhost:3000/.well-known/oauth-protected-resource" , {
92+ headers : {
93+ "Forwarded" : "host=example.org;proto=https" ,
94+ } ,
95+ } ) ;
96+ const res = handler ( req ) ;
97+ const json = await res . json ( ) ;
98+ expect ( json . resource ) . toBe ( "https://example.org" ) ;
99+ } ) ;
100+
101+ it ( "preserves path when using proxy headers" , async ( ) => {
102+ const req = new Request ( "http://localhost:3000/.well-known/oauth-protected-resource/my-resource" , {
103+ headers : {
104+ "X-Forwarded-Host" : "example.org" ,
105+ "X-Forwarded-Proto" : "https" ,
106+ } ,
107+ } ) ;
108+ const res = handler ( req ) ;
109+ const json = await res . json ( ) ;
110+ expect ( json . resource ) . toBe ( "https://example.org/my-resource" ) ;
111+ } ) ;
112+
113+ it ( "falls back to req.url when no proxy headers present" , async ( ) => {
114+ const req = new Request ( "https://direct-server.com/.well-known/oauth-protected-resource" ) ;
115+ const res = handler ( req ) ;
116+ const json = await res . json ( ) ;
117+ expect ( json . resource ) . toBe ( "https://direct-server.com" ) ;
118+ } ) ;
119+ } ) ;
120+
121+ describe ( "explicit resourceUrl override" , ( ) => {
122+ it ( "uses explicit resourceUrl when provided" , async ( ) => {
123+ const handler = protectedResourceHandler ( {
124+ authServerUrls : [ "https://auth-server.com" ] ,
125+ resourceUrl : "https://my-public-domain.com" ,
126+ } ) ;
127+
128+ const req = new Request ( "http://localhost:3000/.well-known/oauth-protected-resource" , {
129+ headers : {
130+ "X-Forwarded-Host" : "different-proxy.org" ,
131+ "X-Forwarded-Proto" : "https" ,
132+ } ,
133+ } ) ;
134+ const res = handler ( req ) ;
135+ const json = await res . json ( ) ;
136+ // Should use explicit override, ignoring both req.url and proxy headers
137+ expect ( json . resource ) . toBe ( "https://my-public-domain.com" ) ;
138+ } ) ;
139+ } ) ;
49140} ) ;
50141
0 commit comments