From e8b4aed5e2b88fde219d9b4f87818b930d99c809 Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Fri, 2 Aug 2019 12:37:41 -0700 Subject: [PATCH 1/8] get domain, port, and scheme from original request for login/logout urls --- .../api/users/dev/LocalUserService.java | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java index e582b3b857..5762107838 100644 --- a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java +++ b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java @@ -4,12 +4,16 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Map; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; import com.google.appengine.tools.development.AbstractLocalRpcService; import com.google.appengine.tools.development.LocalRpcService; import com.google.appengine.tools.development.LocalServiceContext; import com.google.appengine.tools.development.ServiceProvider; import com.google.appengine.tools.resources.ResourceLoader; +import com.google.apphosting.api.ApiProxy; +import com.google.apphosting.api.ApiProxy.Environment; import com.google.apphosting.api.UserServicePb; @@ -35,6 +39,9 @@ public final class LocalUserService extends AbstractLocalRpcService private boolean oauthIsAdmin = false; private final String NGINX_ADDR = "NGINX_ADDR"; private final String DASHBOARD_HTTPS_PORT = "1443"; + private final String apiProxyRequest = "com.google.appengine.http_servlet_request"; + private final int httpScheme = "http://".length(); + private final int httpsScheme = "https://".length(); public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Status status, UserServicePb.CreateLoginURLRequest request ) { @@ -42,10 +49,31 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat String destinationUrl = request.getDestinationUrl(); if(destinationUrl != null && destinationUrl.startsWith("/")) { - String nginxPort = ResourceLoader.getNginxPort(); - destinationUrl = "http://" + System.getProperty(NGINX_ADDR) + ":" + nginxPort + destinationUrl; + Environment env = ApiProxy.getCurrentEnvironment(); + if (env == null) { + throw new RuntimeException("Could not create URL for login request!"); + } + HttpServletRequest req = (HttpServletRequest) env.getAttributes().get(apiProxyRequest); + if (req == null) { + throw new RuntimeException("Could not create URL for login request!"); + } + StringBuffer fullURL = req.getRequestURL(); + String forwardedProto = req.getHeader("X-Forwarded-Proto"); + + // Default start domain length will be http scheme length. + int startOfDomain = httpScheme; + + // If the URL is https, then change the start of domain to https + // (otherwise the index we're testing would not be a '/'). + if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsScheme; } + + // Get the part of URL from the end of the scheme to the beginning of the path. + String destinationPrefix = fullURL.substring(startOfDomain, fullURL.indexOf("/", startOfDomain)); + + // Construct the url. + destinationUrl = forwardedProto + "://" + destinationPrefix + destinationUrl; } - + response.setLoginUrl(LOGIN_URL + "?continue=" + encode(destinationUrl)); return response; } @@ -53,8 +81,33 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat public UserServicePb.CreateLogoutURLResponse createLogoutURL( LocalRpcService.Status status, UserServicePb.CreateLogoutURLRequest request ) { UserServicePb.CreateLogoutURLResponse response = new UserServicePb.CreateLogoutURLResponse(); - String nginxPort = ResourceLoader.getNginxPort(); - String redirect_url = "https://" + LOGIN_SERVER + ":" + DASHBOARD_HTTPS_PORT + "/logout?continue=http://" + LOGIN_SERVER + ":" + nginxPort; + + // Get the port we just came from. + Environment env = ApiProxy.getCurrentEnvironment(); + if (env == null) { + throw new RuntimeException("Could not create URL for logout request!"); + } + HttpServletRequest req = (HttpServletRequest) env.getAttributes().get(apiProxyRequest); + if (req == null) { + throw new RuntimeException("Could not create URL for logout request!"); + } + StringBuffer fullURL = req.getRequestURL(); + String forwardedProto = req.getHeader("X-Forwarded-Proto"); + + // Default start domain length will be http scheme length. + int startOfDomain = httpScheme; + + // If the URL is https, then change the start of domain to https + // (otherwise the index we're testing would not be a '/'). + if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsScheme; } + + // Get the part of URL from the end of the scheme to the beginning of the path. + String destinationPrefix = fullURL.substring(startOfDomain, fullURL.indexOf("/", startOfDomain)); + + // Construct the url. + String destinationUrl = forwardedProto + "://" + destinationPrefix; + + String redirect_url = "https://" + LOGIN_SERVER + ":" + DASHBOARD_HTTPS_PORT + "/logout?continue=" + destinationUrl; response.setLogoutUrl(redirect_url); return response; @@ -74,7 +127,7 @@ public UserServicePb.GetOAuthUserResponse getOAuthUser( LocalRpcService.Status s response.setUserId(this.oauthUserId); response.setAuthDomain(this.oauthAuthDomain); response.setIsAdmin(this.oauthIsAdmin); - + return response; } From 84196a18c5148490ec922c8bd26aba7ac058debf Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Thu, 8 Aug 2019 08:55:41 -0700 Subject: [PATCH 2/8] get scheme from request to create login urls --- AppServer/google/appengine/tools/devappserver2/module.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AppServer/google/appengine/tools/devappserver2/module.py b/AppServer/google/appengine/tools/devappserver2/module.py index a8765d9dbe..854e237b10 100644 --- a/AppServer/google/appengine/tools/devappserver2/module.py +++ b/AppServer/google/appengine/tools/devappserver2/module.py @@ -587,6 +587,11 @@ def _handle_request_impl(self, environ, start_response, inst=None, else: environ['SERVER_PORT'] = 443 + # AppScale: Modify environment based on proxy headers. + x_proto = environ.get('HTTP_X_FORWARDED_PROTO') + if x_proto: + environ['wsgi.url_scheme'] = x_proto + if 'HTTP_HOST' in environ: environ['SERVER_NAME'] = environ['HTTP_HOST'].split(':', 1)[0] environ['DEFAULT_VERSION_HOSTNAME'] = '%s:%s' % ( From 00ee8abbeb3b034c5c057c3c5ee16ebcaae100e6 Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Thu, 8 Aug 2019 16:59:01 -0700 Subject: [PATCH 3/8] change variable name --- .../appengine/api/users/dev/LocalUserService.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java index 5762107838..512c8428cb 100644 --- a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java +++ b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java @@ -40,8 +40,10 @@ public final class LocalUserService extends AbstractLocalRpcService private final String NGINX_ADDR = "NGINX_ADDR"; private final String DASHBOARD_HTTPS_PORT = "1443"; private final String apiProxyRequest = "com.google.appengine.http_servlet_request"; - private final int httpScheme = "http://".length(); - private final int httpsScheme = "https://".length(); + // The length of "http://" + private final int httpSchemeLength = 7; + // The length of "https://" + private final int httpsSchemeLength = 8; public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Status status, UserServicePb.CreateLoginURLRequest request ) { @@ -61,11 +63,11 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat String forwardedProto = req.getHeader("X-Forwarded-Proto"); // Default start domain length will be http scheme length. - int startOfDomain = httpScheme; + int startOfDomain = httpSchemeLength; // If the URL is https, then change the start of domain to https // (otherwise the index we're testing would not be a '/'). - if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsScheme; } + if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsSchemeLength; } // Get the part of URL from the end of the scheme to the beginning of the path. String destinationPrefix = fullURL.substring(startOfDomain, fullURL.indexOf("/", startOfDomain)); @@ -95,11 +97,11 @@ public UserServicePb.CreateLogoutURLResponse createLogoutURL( LocalRpcService.St String forwardedProto = req.getHeader("X-Forwarded-Proto"); // Default start domain length will be http scheme length. - int startOfDomain = httpScheme; + int startOfDomain = httpSchemeLength; // If the URL is https, then change the start of domain to https // (otherwise the index we're testing would not be a '/'). - if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsScheme; } + if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsSchemeLength; } // Get the part of URL from the end of the scheme to the beginning of the path. String destinationPrefix = fullURL.substring(startOfDomain, fullURL.indexOf("/", startOfDomain)); From 7a7cdce4e26f7080afcd1d3089458abc5733e174 Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Thu, 8 Aug 2019 17:23:00 -0700 Subject: [PATCH 4/8] just take the Host header instead of a bunch of string manipulation --- .../api/users/dev/LocalUserService.java | 74 +++++++++++-------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java index 512c8428cb..e9af4f8db3 100644 --- a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java +++ b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java @@ -40,10 +40,9 @@ public final class LocalUserService extends AbstractLocalRpcService private final String NGINX_ADDR = "NGINX_ADDR"; private final String DASHBOARD_HTTPS_PORT = "1443"; private final String apiProxyRequest = "com.google.appengine.http_servlet_request"; - // The length of "http://" - private final int httpSchemeLength = 7; - // The length of "https://" - private final int httpsSchemeLength = 8; + private final String loginURLError = "Could not create URL for createLoginURL request!"; + private final String logoutURLError = "Could not create URL for createLogoutURL request!"; + public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Status status, UserServicePb.CreateLoginURLRequest request ) { @@ -53,27 +52,32 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat { Environment env = ApiProxy.getCurrentEnvironment(); if (env == null) { - throw new RuntimeException("Could not create URL for login request!"); + throw new RuntimeException(loginURLError); } HttpServletRequest req = (HttpServletRequest) env.getAttributes().get(apiProxyRequest); if (req == null) { - throw new RuntimeException("Could not create URL for login request!"); + throw new RuntimeException(loginURLError); } - StringBuffer fullURL = req.getRequestURL(); + String serverPort = ""; + String host = req.getHeader("Host"); String forwardedProto = req.getHeader("X-Forwarded-Proto"); - - // Default start domain length will be http scheme length. - int startOfDomain = httpSchemeLength; - - // If the URL is https, then change the start of domain to https - // (otherwise the index we're testing would not be a '/'). - if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsSchemeLength; } - - // Get the part of URL from the end of the scheme to the beginning of the path. - String destinationPrefix = fullURL.substring(startOfDomain, fullURL.indexOf("/", startOfDomain)); + if (host == null || forwardedProto == null) { + throw new RuntimeException(loginURLError); + } + if (host.split(':').length > 1) { + String httpsPort = req.getHeader("X-Redirect-Https-Port"); + String httpPort = req.getHeader("X-Redirect-Http-Port"); + if (httpsPort == null || httpPort == null) { + throw new RuntimeException(loginURLError); + } + serverPort = ":"; + serverPort += (forwardedProto.equals("https")) + ? (httpsPort) + : (httpPort); + } // Construct the url. - destinationUrl = forwardedProto + "://" + destinationPrefix + destinationUrl; + destinationUrl = forwardedProto + "://" + host + serverPort + destinationUrl; } response.setLoginUrl(LOGIN_URL + "?continue=" + encode(destinationUrl)); @@ -87,27 +91,33 @@ public UserServicePb.CreateLogoutURLResponse createLogoutURL( LocalRpcService.St // Get the port we just came from. Environment env = ApiProxy.getCurrentEnvironment(); if (env == null) { - throw new RuntimeException("Could not create URL for logout request!"); + throw new RuntimeException(logoutURLError); } HttpServletRequest req = (HttpServletRequest) env.getAttributes().get(apiProxyRequest); if (req == null) { - throw new RuntimeException("Could not create URL for logout request!"); + throw new RuntimeException(logoutURLError); } - StringBuffer fullURL = req.getRequestURL(); - String forwardedProto = req.getHeader("X-Forwarded-Proto"); - // Default start domain length will be http scheme length. - int startOfDomain = httpSchemeLength; - - // If the URL is https, then change the start of domain to https - // (otherwise the index we're testing would not be a '/'). - if (fullURL.charAt(startOfDomain) == '/') { startOfDomain = httpsSchemeLength; } - - // Get the part of URL from the end of the scheme to the beginning of the path. - String destinationPrefix = fullURL.substring(startOfDomain, fullURL.indexOf("/", startOfDomain)); + String serverPort = ""; + String host = req.getHeader("Host"); + String forwardedProto = req.getHeader("X-Forwarded-Proto"); + if (host == null || forwardedProto == null) { + throw new RuntimeException(logoutURLError); + } + if (host.split(':').length > 1) { + String httpsPort = req.getHeader("X-Redirect-Https-Port"); + String httpPort = req.getHeader("X-Redirect-Http-Port"); + if (httpsPort == null || httpPort == null) { + throw new RuntimeException(logoutURLError); + } + serverPort = ":"; + serverPort += (forwardedProto.equals("https")) + ? (httpsPort) + : (httpPort); + } // Construct the url. - String destinationUrl = forwardedProto + "://" + destinationPrefix; + destinationUrl = forwardedProto + "://" + host + serverPort + destinationUrl; String redirect_url = "https://" + LOGIN_SERVER + ":" + DASHBOARD_HTTPS_PORT + "/logout?continue=" + destinationUrl; response.setLogoutUrl(redirect_url); From 6fa65635ddf14251ca684d073f7e97901508a3d5 Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Thu, 22 Aug 2019 12:35:17 -0700 Subject: [PATCH 5/8] path unnecessary for logout url --- .../com/google/appengine/api/users/dev/LocalUserService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java index e9af4f8db3..e65a36d047 100644 --- a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java +++ b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java @@ -117,7 +117,7 @@ public UserServicePb.CreateLogoutURLResponse createLogoutURL( LocalRpcService.St } // Construct the url. - destinationUrl = forwardedProto + "://" + host + serverPort + destinationUrl; + String destinationUrl = forwardedProto + "://" + host + serverPort; String redirect_url = "https://" + LOGIN_SERVER + ":" + DASHBOARD_HTTPS_PORT + "/logout?continue=" + destinationUrl; response.setLogoutUrl(redirect_url); From 2fc4df9782eebcc66ab01d0ab53a17dadb43407a Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Thu, 22 Aug 2019 13:50:55 -0700 Subject: [PATCH 6/8] String not char --- .../com/google/appengine/api/users/dev/LocalUserService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java index e65a36d047..631500f362 100644 --- a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java +++ b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java @@ -64,7 +64,7 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat if (host == null || forwardedProto == null) { throw new RuntimeException(loginURLError); } - if (host.split(':').length > 1) { + if (host.split(":").length > 1) { String httpsPort = req.getHeader("X-Redirect-Https-Port"); String httpPort = req.getHeader("X-Redirect-Http-Port"); if (httpsPort == null || httpPort == null) { @@ -104,7 +104,7 @@ public UserServicePb.CreateLogoutURLResponse createLogoutURL( LocalRpcService.St if (host == null || forwardedProto == null) { throw new RuntimeException(logoutURLError); } - if (host.split(':').length > 1) { + if (host.split(":").length > 1) { String httpsPort = req.getHeader("X-Redirect-Https-Port"); String httpPort = req.getHeader("X-Redirect-Http-Port"); if (httpsPort == null || httpPort == null) { From 14b7f44f8091c90553e4041431fe82a1724f1aad Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Fri, 23 Aug 2019 12:58:25 -0700 Subject: [PATCH 7/8] fix server port logic --- .../api/users/dev/LocalUserService.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java index 631500f362..e8b94a9dfd 100644 --- a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java +++ b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java @@ -58,13 +58,14 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat if (req == null) { throw new RuntimeException(loginURLError); } - String serverPort = ""; String host = req.getHeader("Host"); String forwardedProto = req.getHeader("X-Forwarded-Proto"); if (host == null || forwardedProto == null) { throw new RuntimeException(loginURLError); } - if (host.split(":").length > 1) { + String[] hostPieces = host.split(":"); + if (hostPieces.length > 1) { + String serverPort = ""; String httpsPort = req.getHeader("X-Redirect-Https-Port"); String httpPort = req.getHeader("X-Redirect-Http-Port"); if (httpsPort == null || httpPort == null) { @@ -74,10 +75,11 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat serverPort += (forwardedProto.equals("https")) ? (httpsPort) : (httpPort); + host = hostPieces[0] + serverPort; } // Construct the url. - destinationUrl = forwardedProto + "://" + host + serverPort + destinationUrl; + destinationUrl = forwardedProto + "://" + host + destinationUrl; } response.setLoginUrl(LOGIN_URL + "?continue=" + encode(destinationUrl)); @@ -98,26 +100,28 @@ public UserServicePb.CreateLogoutURLResponse createLogoutURL( LocalRpcService.St throw new RuntimeException(logoutURLError); } - String serverPort = ""; String host = req.getHeader("Host"); String forwardedProto = req.getHeader("X-Forwarded-Proto"); if (host == null || forwardedProto == null) { throw new RuntimeException(logoutURLError); } - if (host.split(":").length > 1) { + String[] hostPieces = host.split(":"); + if (hostPieces.length > 1) { + String serverPort = ""; String httpsPort = req.getHeader("X-Redirect-Https-Port"); String httpPort = req.getHeader("X-Redirect-Http-Port"); if (httpsPort == null || httpPort == null) { - throw new RuntimeException(logoutURLError); + throw new RuntimeException(loginURLError); } serverPort = ":"; serverPort += (forwardedProto.equals("https")) ? (httpsPort) : (httpPort); + host = hostPieces[0] + serverPort; } // Construct the url. - String destinationUrl = forwardedProto + "://" + host + serverPort; + String destinationUrl = forwardedProto + "://" + host; String redirect_url = "https://" + LOGIN_SERVER + ":" + DASHBOARD_HTTPS_PORT + "/logout?continue=" + destinationUrl; response.setLogoutUrl(redirect_url); From ed63ffaf5d37cdb35be2dd35b0cc11d17a9c6d6a Mon Sep 17 00:00:00 2001 From: whoarethebritons Date: Mon, 26 Aug 2019 14:33:55 -0700 Subject: [PATCH 8/8] address pr comments, no need to modify host and have default proto be http --- .../api/users/dev/LocalUserService.java | 38 ++++--------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java index e8b94a9dfd..6962d6304d 100644 --- a/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java +++ b/AppServer_Java/src/com/google/appengine/api/users/dev/LocalUserService.java @@ -60,22 +60,11 @@ public UserServicePb.CreateLoginURLResponse createLoginURL( LocalRpcService.Stat } String host = req.getHeader("Host"); String forwardedProto = req.getHeader("X-Forwarded-Proto"); - if (host == null || forwardedProto == null) { - throw new RuntimeException(loginURLError); + if (forwardedProto == null) { + forwardedProto = "http"; } - String[] hostPieces = host.split(":"); - if (hostPieces.length > 1) { - String serverPort = ""; - String httpsPort = req.getHeader("X-Redirect-Https-Port"); - String httpPort = req.getHeader("X-Redirect-Http-Port"); - if (httpsPort == null || httpPort == null) { - throw new RuntimeException(loginURLError); - } - serverPort = ":"; - serverPort += (forwardedProto.equals("https")) - ? (httpsPort) - : (httpPort); - host = hostPieces[0] + serverPort; + if (host == null) { + throw new RuntimeException(loginURLError); } // Construct the url. @@ -102,22 +91,11 @@ public UserServicePb.CreateLogoutURLResponse createLogoutURL( LocalRpcService.St String host = req.getHeader("Host"); String forwardedProto = req.getHeader("X-Forwarded-Proto"); - if (host == null || forwardedProto == null) { - throw new RuntimeException(logoutURLError); + if (forwardedProto == null) { + forwardedProto = "http"; } - String[] hostPieces = host.split(":"); - if (hostPieces.length > 1) { - String serverPort = ""; - String httpsPort = req.getHeader("X-Redirect-Https-Port"); - String httpPort = req.getHeader("X-Redirect-Http-Port"); - if (httpsPort == null || httpPort == null) { - throw new RuntimeException(loginURLError); - } - serverPort = ":"; - serverPort += (forwardedProto.equals("https")) - ? (httpsPort) - : (httpPort); - host = hostPieces[0] + serverPort; + if (host == null) { + throw new RuntimeException(loginURLError); } // Construct the url.