@@ -138,6 +138,91 @@ func (f *fakeAuthService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
138138 http .Error (w , "not found" , http .StatusNotFound )
139139}
140140
141+ func setupAuthServiceStagingMiddlewareTestServer (t * testing.T ) (* SessionStore , * httptest.Server ) {
142+ t .Helper ()
143+
144+ authStub := & fakeAuthService {t : t }
145+ authTS := httptest .NewServer (authStub )
146+ t .Cleanup (authTS .Close )
147+
148+ authClient := dolthubauth .NewClient (dolthubauth.ClientConfig {
149+ BaseURL : authTS .URL ,
150+ TenantID : "tenant-1" ,
151+ Environment : "staging" ,
152+ KeyID : "kid-1" ,
153+ SharedSecret : "shared-secret" ,
154+ Now : func () time.Time {
155+ return time .Date (2026 , 4 , 8 , 12 , 0 , 0 , 0 , time .UTC )
156+ },
157+ })
158+
159+ sessions := NewSessionStore ()
160+ resolver := NewAuthServiceWorkspaceResolver (authClient , sessions )
161+ t .Cleanup (resolver .Stop )
162+
163+ hostedServer := NewAuthServiceServer (resolver , sessions , authClient , "session-secret" , "subject-secret" , "staging" )
164+ inner := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
165+ client , ok := ClientFromContext (r .Context ())
166+ if ! ok {
167+ w .WriteHeader (http .StatusInternalServerError )
168+ return
169+ }
170+ scope , _ := api .ResolvedReadIdentityFromContext (r .Context ())
171+ writeJSON (w , http .StatusOK , map [string ]string {
172+ "rig_handle" : client .RigHandle (),
173+ "upstream" : scope .Upstream ,
174+ "viewer" : scope .Viewer ,
175+ })
176+ })
177+
178+ mux := http .NewServeMux ()
179+ mux .Handle ("/" , hostedServer .AuthMiddleware (inner ))
180+ ts := httptest .NewServer (mux )
181+ t .Cleanup (ts .Close )
182+ return sessions , ts
183+ }
184+
185+ func TestAuthServiceAuthMiddleware_Impersonate_Staging_POST_Allowed (t * testing.T ) {
186+ sessions , ts := setupAuthServiceStagingMiddlewareTestServer (t )
187+ sessionID , err := sessions .CreateWithSubject ("conn-1" , "subject-1" )
188+ if err != nil {
189+ t .Fatalf ("CreateWithSubject() error = %v" , err )
190+ }
191+
192+ req , err := http .NewRequest (http .MethodPost , ts .URL + "/api/wanted" , nil )
193+ if err != nil {
194+ t .Fatalf ("new request: %v" , err )
195+ }
196+ req .AddCookie (& http.Cookie {Name : cookieName , Value : SignSessionCookie (sessionID , "conn-1" , "session-secret" )})
197+ req .AddCookie (& http.Cookie {Name : subjectCookieName , Value : SignSubjectID ("subject-1" , "subject-secret" )})
198+ req .Header .Set ("X-Wasteland" , "hop/wl-commons" )
199+ req .Header .Set ("X-Impersonate" , "bob" )
200+
201+ resp , err := http .DefaultClient .Do (req )
202+ if err != nil {
203+ t .Fatalf ("POST /api/wanted: %v" , err )
204+ }
205+ defer func () { _ = resp .Body .Close () }()
206+ if resp .StatusCode != http .StatusOK {
207+ body , _ := io .ReadAll (resp .Body )
208+ t .Fatalf ("expected 200, got %d: %s" , resp .StatusCode , string (body ))
209+ }
210+
211+ var result map [string ]string
212+ if err := json .NewDecoder (resp .Body ).Decode (& result ); err != nil {
213+ t .Fatalf ("decode response: %v" , err )
214+ }
215+ if result ["rig_handle" ] != "bob" {
216+ t .Fatalf ("rig_handle = %q, want bob" , result ["rig_handle" ])
217+ }
218+ if result ["viewer" ] != "alice" {
219+ t .Fatalf ("viewer = %q, want alice" , result ["viewer" ])
220+ }
221+ if result ["upstream" ] == "" {
222+ t .Fatal ("expected resolved upstream to be set" )
223+ }
224+ }
225+
141226func TestAuthServiceHostedEndToEnd (t * testing.T ) {
142227 authStub := & fakeAuthService {t : t }
143228 authTS := httptest .NewServer (authStub )
0 commit comments