Skip to content

Commit 24b4631

Browse files
authored
[oidc proxy] Improve handling of redirects from protected resource (#9080)
1 parent c2db603 commit 24b4631

File tree

2 files changed

+78
-3
lines changed

2 files changed

+78
-3
lines changed

ydb/mvp/oidc_proxy/oidc_protected_page.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,20 @@ class THandlerSessionServiceCheck : public NActors::TActorBootstrapped<THandlerS
229229
TString GetFixedLocationHeader(TStringBuf location) {
230230
TStringBuf scheme, host, uri;
231231
NHttp::CrackURL(ProtectedPageUrl, scheme, host, uri);
232-
return TStringBuilder() << '/' << host << location;
232+
if (location.StartsWith("//")) {
233+
return TStringBuilder() << '/' << (scheme.empty() ? "" : TString(scheme) + "://") << location.SubStr(2);
234+
} else if (location.StartsWith('/')) {
235+
return TStringBuilder() << '/'
236+
<< (scheme.empty() ? "" : TString(scheme) + "://")
237+
<< host << location;
238+
} else {
239+
TStringBuf locScheme, locHost, locUri;
240+
NHttp::CrackURL(location, locScheme, locHost, locUri);
241+
if (!locScheme.empty()) {
242+
return TStringBuilder() << '/' << location;
243+
}
244+
}
245+
return TString(location);
233246
}
234247

235248
NHttp::THttpOutgoingResponsePtr CreateResponseForbiddenHost() {

ydb/mvp/oidc_proxy/oidc_proxy_ut.cpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ Y_UNIT_TEST_SUITE(Mvp) {
277277
std::unique_ptr<grpc::Server> sessionServer(builder.BuildAndStart());
278278

279279
NHttp::THttpIncomingRequestPtr incomingRequest = new NHttp::THttpIncomingRequest();
280-
EatWholeString(incomingRequest, "GET /" + allowedProxyHost + "/counters HTTP/1.1\r\n"
280+
EatWholeString(incomingRequest, "GET /http://" + allowedProxyHost + "/counters HTTP/1.1\r\n"
281281
"Host: oidcproxy.net\r\n"
282282
"Cookie: yc_session=allowed_session_cookie\r\n\r\n");
283283
runtime.Send(new IEventHandle(target, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingRequest(incomingRequest)));
@@ -288,6 +288,8 @@ Y_UNIT_TEST_SUITE(Mvp) {
288288
UNIT_ASSERT_STRINGS_EQUAL(outgoingRequestEv->Request->URL, "/counters");
289289
UNIT_ASSERT_STRING_CONTAINS(outgoingRequestEv->Request->Headers, "Authorization: Bearer protected_page_iam_token");
290290
UNIT_ASSERT_EQUAL(outgoingRequestEv->Request->Secure, false);
291+
292+
// Location start with '/'
291293
NHttp::THttpIncomingResponsePtr incomingResponse = new NHttp::THttpIncomingResponse(outgoingRequestEv->Request);
292294
EatWholeString(incomingResponse, "HTTP/1.1 307 Temporary Redirect\r\n"
293295
"Connection: close\r\n"
@@ -297,7 +299,67 @@ Y_UNIT_TEST_SUITE(Mvp) {
297299

298300
auto outgoingResponseEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingResponse>(handle);
299301
UNIT_ASSERT_STRINGS_EQUAL(outgoingResponseEv->Response->Status, "307");
300-
UNIT_ASSERT_STRING_CONTAINS(outgoingResponseEv->Response->Headers, "Location: /" + allowedProxyHost + "/node/12345/counters");
302+
UNIT_ASSERT_STRING_CONTAINS(outgoingResponseEv->Response->Headers, "Location: /http://" + allowedProxyHost + "/node/12345/counters");
303+
304+
// Location start with "//"
305+
runtime.Send(new IEventHandle(target, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingRequest(incomingRequest)));
306+
outgoingRequestEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingRequest>(handle);
307+
308+
incomingResponse = new NHttp::THttpIncomingResponse(outgoingRequestEv->Request);
309+
EatWholeString(incomingResponse, "HTTP/1.1 302 Found\r\n"
310+
"Connection: close\r\n"
311+
"Location: //new.oidc.proxy.host:1234/node/12345/counters\r\n"
312+
"Content-Length:0\r\n\r\n");
313+
runtime.Send(new IEventHandle(handle->Sender, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingResponse(outgoingRequestEv->Request, incomingResponse)));
314+
315+
outgoingResponseEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingResponse>(handle);
316+
UNIT_ASSERT_STRINGS_EQUAL(outgoingResponseEv->Response->Status, "302");
317+
UNIT_ASSERT_STRING_CONTAINS(outgoingResponseEv->Response->Headers, "Location: /http://new.oidc.proxy.host:1234/node/12345/counters");
318+
319+
// Location start with ".."
320+
runtime.Send(new IEventHandle(target, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingRequest(incomingRequest)));
321+
outgoingRequestEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingRequest>(handle);
322+
323+
incomingResponse = new NHttp::THttpIncomingResponse(outgoingRequestEv->Request);
324+
EatWholeString(incomingResponse, "HTTP/1.1 302 Found\r\n"
325+
"Connection: close\r\n"
326+
"Location: ../node/12345/counters\r\n"
327+
"Content-Length:0\r\n\r\n");
328+
runtime.Send(new IEventHandle(handle->Sender, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingResponse(outgoingRequestEv->Request, incomingResponse)));
329+
330+
outgoingResponseEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingResponse>(handle);
331+
UNIT_ASSERT_STRINGS_EQUAL(outgoingResponseEv->Response->Status, "302");
332+
UNIT_ASSERT_STRING_CONTAINS(outgoingResponseEv->Response->Headers, "Location: ../node/12345/counters");
333+
334+
// Location is absolute URL
335+
runtime.Send(new IEventHandle(target, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingRequest(incomingRequest)));
336+
outgoingRequestEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingRequest>(handle);
337+
338+
incomingResponse = new NHttp::THttpIncomingResponse(outgoingRequestEv->Request);
339+
EatWholeString(incomingResponse, "HTTP/1.1 302 Found\r\n"
340+
"Connection: close\r\n"
341+
"Location: https://some.new.oidc.host:9876/counters/v1\r\n"
342+
"Content-Length:0\r\n\r\n");
343+
runtime.Send(new IEventHandle(handle->Sender, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingResponse(outgoingRequestEv->Request, incomingResponse)));
344+
345+
outgoingResponseEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingResponse>(handle);
346+
UNIT_ASSERT_STRINGS_EQUAL(outgoingResponseEv->Response->Status, "302");
347+
UNIT_ASSERT_STRING_CONTAINS(outgoingResponseEv->Response->Headers, "Location: /https://some.new.oidc.host:9876/counters/v1");
348+
349+
// Location is sub-resources URL
350+
runtime.Send(new IEventHandle(target, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingRequest(incomingRequest)));
351+
outgoingRequestEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingRequest>(handle);
352+
353+
incomingResponse = new NHttp::THttpIncomingResponse(outgoingRequestEv->Request);
354+
EatWholeString(incomingResponse, "HTTP/1.1 302 Found\r\n"
355+
"Connection: close\r\n"
356+
"Location: v1/\r\n"
357+
"Content-Length:0\r\n\r\n");
358+
runtime.Send(new IEventHandle(handle->Sender, edge, new NHttp::TEvHttpProxy::TEvHttpIncomingResponse(outgoingRequestEv->Request, incomingResponse)));
359+
360+
outgoingResponseEv = runtime.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpOutgoingResponse>(handle);
361+
UNIT_ASSERT_STRINGS_EQUAL(outgoingResponseEv->Response->Status, "302");
362+
UNIT_ASSERT_STRING_CONTAINS(outgoingResponseEv->Response->Headers, "Location: v1/");
301363
}
302364

303365

0 commit comments

Comments
 (0)