Repository: knox Updated Branches: refs/heads/master 06df07ec9 -> 8ba9d9235
KNOX-1314 - SSOCookieProvider should be able to derive a default provider URL Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/8ba9d923 Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/8ba9d923 Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/8ba9d923 Branch: refs/heads/master Commit: 8ba9d923501e8a5f016133030dd328cf2d33855a Parents: 06df07e Author: Larry McCay <lmc...@hw14155.home> Authored: Thu May 17 12:52:20 2018 -0400 Committer: Larry McCay <lmc...@hw14155.home> Committed: Thu May 17 12:52:58 2018 -0400 ---------------------------------------------------------------------- .../provider/federation/jwt/JWTMessages.java | 2 +- .../jwt/filter/SSOCookieFederationFilter.java | 35 +++++++++++++- .../federation/SSOCookieProviderTest.java | 50 ++++++++++++++++++-- 3 files changed, 79 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/8ba9d923/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/JWTMessages.java ---------------------------------------------------------------------- diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/JWTMessages.java b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/JWTMessages.java index 70efa8c..5f43395 100644 --- a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/JWTMessages.java +++ b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/JWTMessages.java @@ -49,7 +49,7 @@ public interface JWTMessages { @Message( level = MessageLevel.DEBUG, text = "Sending redirect to: {0}" ) void sendRedirectToLoginURL(String loginURL); - @Message( level = MessageLevel.ERROR, text = "Required configuration element for authentication provider is missing." ) + @Message( level = MessageLevel.WARN, text = "Configuration for authentication provider URL is missing - will derive default URL." ) void missingAuthenticationProviderUrlConfiguration(); @Message( level = MessageLevel.DEBUG, text = "{0} Cookie has been found and is being processed." ) http://git-wip-us.apache.org/repos/asf/knox/blob/8ba9d923/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java ---------------------------------------------------------------------- diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java index 1a43e3a..8537ee0 100644 --- a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java +++ b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java @@ -42,6 +42,9 @@ public class SSOCookieFederationFilter extends AbstractJWTFilter { public static final String SSO_EXPECTED_AUDIENCES = "sso.expected.audiences"; public static final String SSO_AUTHENTICATION_PROVIDER_URL = "sso.authentication.provider.url"; public static final String SSO_VERIFICATION_PEM = "sso.token.verification.pem"; + public static final String X_FORWARDED_HOST = "X-Forwarded-Host"; + public static final String X_FORWARDED_PORT = "X-Forwarded-Port"; + public static final String X_FORWARDED_PROTO = "X-Forwarded-Proto"; private static final String ORIGINAL_URL_QUERY_PARAM = "originalUrl="; private static final String DEFAULT_SSO_COOKIE_NAME = "hadoop-jwt"; @@ -72,7 +75,6 @@ public class SSOCookieFederationFilter extends AbstractJWTFilter { authenticationProviderUrl = filterConfig.getInitParameter(SSO_AUTHENTICATION_PROVIDER_URL); if (authenticationProviderUrl == null) { log.missingAuthenticationProviderUrlConfiguration(); - throw new ServletException("Required authentication provider URL is missing."); } // token verification pem @@ -169,6 +171,9 @@ public class SSOCookieFederationFilter extends AbstractJWTFilter { */ protected String constructLoginURL(HttpServletRequest request) { String delimiter = "?"; + if (authenticationProviderUrl == null) { + authenticationProviderUrl = deriveDefaultAuthenticationProviderUrl(request); + } if (authenticationProviderUrl.contains("?")) { delimiter = "&"; } @@ -178,9 +183,35 @@ public class SSOCookieFederationFilter extends AbstractJWTFilter { return loginURL; } + /** + * Derive a provider URL from the request assuming that the + * KnoxSSO endpoint is local to the endpoint serving this request. + * @param request + * @return + */ + public String deriveDefaultAuthenticationProviderUrl(HttpServletRequest request) { + String scheme = null; + String host = null; + int port = 0; + if (!beingProxied(request)) { + scheme = request.getScheme(); + host = request.getServerName(); + port = request.getServerPort(); + } + else { + scheme = request.getHeader(X_FORWARDED_PROTO); + host = request.getHeader(X_FORWARDED_HOST); + port = Integer.parseInt(request.getHeader(X_FORWARDED_PORT)); + } + return scheme + "://" + host + ":" + port + "/" + "gateway/knoxsso/api/v1/websso"; + } + + private boolean beingProxied(HttpServletRequest request) { + return (request.getHeader(X_FORWARDED_HOST) != null); + } + private String getOriginalQueryString(HttpServletRequest request) { String originalQueryString = request.getQueryString(); return (originalQueryString == null) ? "" : "?" + originalQueryString; } - } http://git-wip-us.apache.org/repos/asf/knox/blob/8ba9d923/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java ---------------------------------------------------------------------- diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java index 50a44ce..3aa4cb4 100644 --- a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java +++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java @@ -102,12 +102,10 @@ public class SSOCookieProviderTest extends AbstractJWTFilterTest { Properties props = getProperties(); props.remove("sso.authentication.provider.url"); handler.init(new TestFilterConfig(props)); - - fail("Servlet exception should have been thrown."); - } catch (ServletException se) { - // expected - let's ensure it mentions the missing authentication provider URL - se.getMessage().contains("authentication provider URL is missing"); + // no longer expected - let's ensure it mentions the missing authentication provider URL + fail("Servlet exception should have been thrown."); + se.printStackTrace(); } } @@ -143,6 +141,48 @@ public class SSOCookieProviderTest extends AbstractJWTFilterTest { Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL, loginURL); } + @Test + public void testDefaultAuthenticationProviderURL() throws Exception { + Properties props = new Properties(); + handler.init(new TestFilterConfig(props)); + + HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class); + EasyMock.expect(request.getRequestURL()).andReturn(new StringBuffer(SERVICE_URL)).anyTimes(); + EasyMock.expect(request.getQueryString()).andReturn(null); + EasyMock.expect(request.getScheme()).andReturn("https").anyTimes(); + EasyMock.expect(request.getServerName()).andReturn("localhost").anyTimes(); + EasyMock.expect(request.getServerPort()).andReturn(8443).anyTimes(); + EasyMock.replay(request); + + String providerURL = ((TestSSOCookieFederationProvider) handler).deriveDefaultAuthenticationProviderUrl(request); + Assert.assertNotNull("LoginURL should not be null.", providerURL); + Assert.assertEquals(providerURL, "https://localhost:8443/gateway/knoxsso/api/v1/websso"); + + String loginURL = ((TestSSOCookieFederationProvider) handler).testConstructLoginURL(request); + Assert.assertNotNull("LoginURL should not be null.", loginURL); + Assert.assertEquals(loginURL, "https://localhost:8443/gateway/knoxsso/api/v1/websso?originalUrl=" + SERVICE_URL); + } + + @Test + public void testProxiedDefaultAuthenticationProviderURL() throws Exception { + Properties props = new Properties(); + handler.init(new TestFilterConfig(props)); + + HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class); + EasyMock.expect(request.getRequestURL()).andReturn(new StringBuffer(SERVICE_URL)).anyTimes(); + EasyMock.expect(request.getHeader(SSOCookieFederationFilter.X_FORWARDED_PROTO)).andReturn("https").anyTimes(); + EasyMock.expect(request.getHeader(SSOCookieFederationFilter.X_FORWARDED_HOST)).andReturn("remotehost").anyTimes(); + EasyMock.expect(request.getHeader(SSOCookieFederationFilter.X_FORWARDED_PORT)).andReturn("8443").anyTimes(); + EasyMock.replay(request); + + String providerURL = ((TestSSOCookieFederationProvider) handler).deriveDefaultAuthenticationProviderUrl(request); + Assert.assertNotNull("LoginURL should not be null.", providerURL); + Assert.assertEquals(providerURL, "https://remotehost:8443/gateway/knoxsso/api/v1/websso"); + + String loginURL = ((TestSSOCookieFederationProvider) handler).testConstructLoginURL(request); + Assert.assertNotNull("LoginURL should not be null.", loginURL); + Assert.assertEquals(loginURL, "https://remotehost:8443/gateway/knoxsso/api/v1/websso?originalUrl=" + SERVICE_URL); + } @Override protected String getVerificationPemProperty() {