From c7139f882628db3405bcfe30941c244b3cda210c Mon Sep 17 00:00:00 2001 From: Ann Catton Date: Thu, 25 Mar 2021 11:13:36 -0400 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=9A=B8=20Adding=20providerType=20to?= =?UTF-8?q?=20access=5Fdenied=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SSOAuthenticationFailureHandler.java | 34 +++++++------ .../SSOAuthenticationFailureHandlerTest.java | 49 +++++++++++++++++-- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/main/java/bio/overture/ego/model/exceptions/SSOAuthenticationFailureHandler.java b/src/main/java/bio/overture/ego/model/exceptions/SSOAuthenticationFailureHandler.java index 9ff65c67..e2d608b1 100644 --- a/src/main/java/bio/overture/ego/model/exceptions/SSOAuthenticationFailureHandler.java +++ b/src/main/java/bio/overture/ego/model/exceptions/SSOAuthenticationFailureHandler.java @@ -50,10 +50,12 @@ public void onAuthenticationFailure( try { URIBuilder errorUri = new URIBuilder(errorRedirect); errorUri.addParameter(ERROR_CODE_PARAM, "403"); + val reqUri = new ArrayList<>(asList(request.getRequestURI().split("/"))); + val providerType = reqUri.get(reqUri.size() - 1).toUpperCase(); if (rootExceptionThrowable instanceof NoPrimaryEmailException) { - errorUri = buildNoPrimaryExceptionResponse(request, errorUri); + errorUri = buildNoPrimaryEmailExceptionResponse(errorUri, providerType); } else if (rootExceptionThrowable instanceof OAuth2Exception) { - errorUri = buildOAuth2ExceptionResponse(errorUri); + errorUri = buildOAuth2ExceptionResponse(errorUri, providerType); } else { throw new InternalServerException("Invalid response from OAuth Service"); } @@ -67,20 +69,10 @@ public void onAuthenticationFailure( } // A user's email is not visible in the IdP token response - public URIBuilder buildNoPrimaryExceptionResponse(HttpServletRequest req, URIBuilder uri) + public URIBuilder buildNoPrimaryEmailExceptionResponse(URIBuilder uri, String providerType) throws InternalServerException { - val reqUri = new ArrayList<>(asList(req.getRequestURI().split("/"))); - val provider = reqUri.get(reqUri.size() - 1).toUpperCase(); uri.addParameter(ERROR_TYPE_PARAM, "no_primary_email"); - try { - ProviderType.resolveProviderType(provider); - uri.addParameter(PROVIDER_TYPE_PARAM, provider); - } catch (IllegalArgumentException e) { - val errMessage = format("Invalid provider: '%s'", provider); - log.warn(errMessage); - throw new IllegalArgumentException(errMessage); - } - return uri; + return buildUriWithProviderTypeParam(uri, providerType); } // A user denies Ego access/cancels login, catch both as "access_denied" @@ -90,8 +82,20 @@ public URIBuilder buildNoPrimaryExceptionResponse(HttpServletRequest req, URIBui // - LinkedIn throws an OAuth2Exception with param error=invalid_request, // so catching this + Orcid and Github under that ex type, as UserDeniedAuthorizationException // inherits from OAuth2Exception - public URIBuilder buildOAuth2ExceptionResponse(URIBuilder uri) { + public URIBuilder buildOAuth2ExceptionResponse(URIBuilder uri, String providerType) { uri.addParameter(ERROR_TYPE_PARAM, "access_denied"); + return buildUriWithProviderTypeParam(uri, providerType); + } + + private URIBuilder buildUriWithProviderTypeParam(URIBuilder uri, String provider) { + try { + ProviderType.resolveProviderType(provider); + uri.addParameter(PROVIDER_TYPE_PARAM, provider); + } catch (IllegalArgumentException e) { + val errMessage = format("Invalid provider: '%s'", provider); + log.warn(errMessage); + throw new IllegalArgumentException(errMessage); + } return uri; } } diff --git a/src/test/java/bio/overture/ego/utils/SSOAuthenticationFailureHandlerTest.java b/src/test/java/bio/overture/ego/utils/SSOAuthenticationFailureHandlerTest.java index fd590ebd..c2da93e8 100644 --- a/src/test/java/bio/overture/ego/utils/SSOAuthenticationFailureHandlerTest.java +++ b/src/test/java/bio/overture/ego/utils/SSOAuthenticationFailureHandlerTest.java @@ -82,15 +82,20 @@ public void noPrimaryEmail_validProviderParam_createRedirectWithParams() { } assertNotNull(uri); - val errorUri = ssoAuthenticationFailureHandler.buildNoPrimaryExceptionResponse(request, uri); + val errorUri = + ssoAuthenticationFailureHandler.buildNoPrimaryEmailExceptionResponse( + uri, validProvider.toString()); Map errorParams = errorUri.getQueryParams().stream() .collect(Collectors.toImmutableMap(NameValuePair::getName, NameValuePair::getValue)); + // assert all params are present assertTrue(errorParams.containsKey(ERROR_TYPE_PARAM)); assertTrue(errorParams.containsKey(ERROR_CODE_PARAM)); assertTrue(errorParams.containsKey(PROVIDER_TYPE_PARAM)); + + // assert param values match expected values assertEquals(errorParams.get(ERROR_TYPE_PARAM), "no_primary_email"); assertEquals(errorParams.get(ERROR_CODE_PARAM), "403"); assertEquals(errorParams.get(PROVIDER_TYPE_PARAM), validProvider.toString()); @@ -118,13 +123,18 @@ public void noPrimaryEmail_invalidProvider_IllegalArgumentException() { assertNotNull(uri); exceptionRule.expect(IllegalArgumentException.class); - ssoAuthenticationFailureHandler.buildNoPrimaryExceptionResponse(request, uri); + ssoAuthenticationFailureHandler.buildNoPrimaryEmailExceptionResponse(uri, invalidProvider); } @SneakyThrows @Test - public void oAuth2Exception_validErrorRedirect_createResponseWithParams() { + public void oAuth2Exception_validProviderParam_createRedirectWithParams() { val app = appWithUrls("https://example-ego.com/redirect"); + val validProvider = ProviderType.LINKEDIN; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setScheme("https"); + request.setServerName("www.example-ego.com"); + request.setRequestURI(String.format("/oauth/login/%s", validProvider.toString().toLowerCase())); URIBuilder uri = null; try { @@ -138,16 +148,47 @@ public void oAuth2Exception_validErrorRedirect_createResponseWithParams() { } assertNotNull(uri); - val errorUri = ssoAuthenticationFailureHandler.buildOAuth2ExceptionResponse(uri); + val errorUri = + ssoAuthenticationFailureHandler.buildOAuth2ExceptionResponse(uri, validProvider.toString()); Map errorParams = errorUri.getQueryParams().stream() .collect(Collectors.toImmutableMap(NameValuePair::getName, NameValuePair::getValue)); + // assert all params are present assertTrue(errorParams.containsKey(ERROR_TYPE_PARAM)); assertTrue(errorParams.containsKey(ERROR_CODE_PARAM)); + assertTrue(errorParams.containsKey(PROVIDER_TYPE_PARAM)); + + // assert param values match expected values assertEquals(errorParams.get(ERROR_TYPE_PARAM), "access_denied"); assertEquals(errorParams.get(ERROR_CODE_PARAM), "403"); + assertEquals(errorParams.get(PROVIDER_TYPE_PARAM), validProvider.toString()); + } + + @SneakyThrows + @Test + public void oAuth2Exception_invalidProvider_IllegalArgumentException() { + val app = appWithUrls("https://example-ego.com/redirect"); + val invalidProvider = "veryInvalid"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setScheme("https"); + request.setServerName("www.example-ego.com"); + request.setRequestURI(String.format("/oauth/login/%s", invalidProvider)); + URIBuilder uri = null; + try { + uri = new URIBuilder(app.getErrorRedirectUri()); + uri.addParameter(ERROR_CODE_PARAM, "403"); + } catch (URISyntaxException e) { + assertEquals( + format("Invalid redirect uri from application: '%s", app.getName()), + URISyntaxException.class, + e.getClass()); + } + + assertNotNull(uri); + exceptionRule.expect(IllegalArgumentException.class); + ssoAuthenticationFailureHandler.buildOAuth2ExceptionResponse(uri, invalidProvider); } @SneakyThrows From 38aaa11857b3098dca385258a5a0d4c0fc1db77c Mon Sep 17 00:00:00 2001 From: Dusan Andric Date: Thu, 25 Mar 2021 11:26:37 -0400 Subject: [PATCH 2/3] next snapshot --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d14b44ca..b1c1598e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ bio.overture ego - 4.3.0 + 4.4.0-SNAPSHOT ego OAuth 2.0 Authorization service that supports multiple OpenID Connect Providers From cef51a71e9d5631491cc8bcd0a0370b7ba047433 Mon Sep 17 00:00:00 2001 From: Ann Catton Date: Thu, 25 Mar 2021 14:17:06 -0400 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=94=96=20rc=204.4.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b1c1598e..715230c9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ bio.overture ego - 4.4.0-SNAPSHOT + 4.4.0 ego OAuth 2.0 Authorization service that supports multiple OpenID Connect Providers