diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml index 7a0459a37bb..db6aa3f59de 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml @@ -167,21 +167,19 @@ org.wso2.tomcat tomcat-servlet-api - - org.wso2.carbon - org.wso2.carbon.logging - org.wso2.carbon org.wso2.carbon.tomcat.ext - org.wso2.carbon.identity.framework org.wso2.carbon.identity.base + + + org.opensaml + xmltooling + + org.wso2.carbon.identity.framework @@ -190,6 +188,12 @@ org.wso2.carbon.identity.inbound.auth.oauth2 org.wso2.carbon.identity.oauth + org.wso2.carbon @@ -258,6 +262,16 @@ org.wso2.carbon.identity.jwt.client.extension test + + org.slf4j + slf4j-nop + test + + + org.apache.sling + org.apache.sling.testing.osgi-mock + test + diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java index 7f9a8bb54c4..9176f461aa0 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.base.ServerConfiguration; +import org.wso2.carbon.certificate.mgt.core.bean.Certificate; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.util.KeyStoreManager; import org.wso2.carbon.registry.core.exceptions.RegistryException; @@ -100,7 +101,7 @@ public class JWTAuthenticator implements WebappAuthenticator { requestUri = ""; } StringTokenizer tokenizer = new StringTokenizer(requestUri, "/"); - String context = tokenizer.nextToken(); + String context = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; if (context == null || "".equals(context)) { authenticationInfo.setStatus(Status.CONTINUE); } @@ -114,7 +115,8 @@ public class JWTAuthenticator implements WebappAuthenticator { issuer = jwsObject.getJWTClaimsSet().getIssuer(); } catch (ParseException e) { log.error("Error occurred while parsing JWT header.", e); - return null; + authenticationInfo.setMessage("Error occured while parsing JWT header"); + return authenticationInfo; } try { @@ -135,7 +137,8 @@ public class JWTAuthenticator implements WebappAuthenticator { String trustStorePassword = serverConfig.getFirstProperty( DEFAULT_TRUST_STORE_PASSWORD); keyStore.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray()); - publicKey = keyStore.getCertificate(alias).getPublicKey(); + java.security.cert.Certificate certificate = keyStore.getCertificate(alias); + publicKey = certificate == null ? null : certificate.getPublicKey(); } else { authenticationInfo.setStatus(Status.FAILURE); return authenticationInfo; @@ -157,26 +160,25 @@ public class JWTAuthenticator implements WebappAuthenticator { } if (verifier != null && jwsObject.verify(verifier)) { username = MultitenantUtils.getTenantAwareUsername(username); - if (tenantId == -1) { - log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " + - ": " + tenantDomain); + UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). + getTenantUserRealm(tenantId).getUserStoreManager(); + if (userStore.isExistingUser(username)) { + authenticationInfo.setTenantId(tenantId); + authenticationInfo.setUsername(username); + authenticationInfo.setTenantDomain(tenantDomain); + authenticationInfo.setStatus(Status.CONTINUE); } else { - UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). - getTenantUserRealm(tenantId).getUserStoreManager(); - if (userStore.isExistingUser(username)) { - authenticationInfo.setTenantId(tenantId); - authenticationInfo.setUsername(username); - authenticationInfo.setTenantDomain(tenantDomain); - authenticationInfo.setStatus(Status.CONTINUE); - } + authenticationInfo.setStatus(Status.FAILURE); } } else { authenticationInfo.setStatus(Status.FAILURE); } } catch (UserStoreException e) { log.error("Error occurred while obtaining the user.", e); + authenticationInfo.setStatus(Status.FAILURE); } catch (Exception e) { log.error("Error occurred while verifying the JWT header.", e); + authenticationInfo.setStatus(Status.FAILURE); } finally { PrivilegedCarbonContext.endTenantFlow(); } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticatorTest.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticatorTest.java index 5ea9b1f88bd..e3e3cf22f72 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticatorTest.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticatorTest.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package org.wso2.carbon.webapp.authenticator.framework.authenticator; import org.apache.catalina.connector.Request; @@ -11,13 +29,9 @@ import org.wso2.carbon.identity.jwt.client.extension.dto.JWTConfig; import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; import org.wso2.carbon.identity.jwt.client.extension.util.JWTClientUtil; import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; -import org.wso2.carbon.webapp.authenticator.framework.internal.AuthenticatorFrameworkDataHolder; -import org.wso2.carbon.webapp.authenticator.framework.util.TestTenantIndexingLoader; -import org.wso2.carbon.webapp.authenticator.framework.util.TestTenantRegistryLoader; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Field; import java.net.URL; @@ -30,6 +44,8 @@ public class JWTAuthenticatorTest { private Field headersField; private final String JWT_HEADER = "X-JWT-Assertion"; private String jwtToken; + private String wrongJwtToken; + private String jwtTokenWithWrongUser; private static final String SIGNED_JWT_AUTH_USERNAME = "http://wso2.org/claims/enduser"; private static final String SIGNED_JWT_AUTH_TENANT_ID = "http://wso2.org/claims/enduserTenantId"; private Properties properties; @@ -39,9 +55,6 @@ public class JWTAuthenticatorTest { @BeforeClass public void setup() throws NoSuchFieldException, IOException, JWTClientException { jwtAuthenticator = new JWTAuthenticator(); - properties = new Properties(); - properties.setProperty(ISSUER, ALIAS); - jwtAuthenticator.setProperties(properties); headersField = org.apache.coyote.Request.class.getDeclaredField("headers"); headersField.setAccessible(true); ClassLoader classLoader = getClass().getClassLoader(); @@ -60,9 +73,17 @@ public class JWTAuthenticatorTest { customClaims.put(SIGNED_JWT_AUTH_USERNAME, "admin"); customClaims.put(SIGNED_JWT_AUTH_TENANT_ID, String.valueOf(MultitenantConstants.SUPER_TENANT_ID)); jwtToken = JWTClientUtil.generateSignedJWTAssertion("admin", jwtConfig, false, customClaims); + customClaims = new HashMap<>(); + customClaims.put(SIGNED_JWT_AUTH_USERNAME, "admin"); + customClaims.put(SIGNED_JWT_AUTH_TENANT_ID, "-1"); + wrongJwtToken = JWTClientUtil.generateSignedJWTAssertion("admin", jwtConfig, false, customClaims); + customClaims = new HashMap<>(); + customClaims.put(SIGNED_JWT_AUTH_USERNAME, "notexisting"); + customClaims.put(SIGNED_JWT_AUTH_TENANT_ID, String.valueOf(MultitenantConstants.SUPER_TENANT_ID)); + jwtTokenWithWrongUser = JWTClientUtil.generateSignedJWTAssertion("notexisting", jwtConfig, false, customClaims); } - @Test(description = "This method tests the get methods in the JWTAuthenticator") + @Test(description = "This method tests the get methods in the JWTAuthenticator", dependsOnMethods = "testAuthenticate") public void testGetMethods() { Assert.assertEquals(jwtAuthenticator.getName(), "JWT", "GetName method returns wrong value"); Assert.assertNotNull(jwtAuthenticator.getProperties(), "Properties are not properly added to JWT " @@ -87,8 +108,61 @@ public class JWTAuthenticatorTest { Assert.assertTrue(jwtAuthenticator.canHandle(request)); } - @Test(description = "This method tests authenticate method under the successful condition") + @Test(description = "This method tests authenticate method under the successful condition", dependsOnMethods = + {"testAuthentiateFailureScenarios"}) public void testAuthenticate() throws IllegalAccessException, NoSuchFieldException { + Request request = createJWTRequest(jwtToken, "test"); + AuthenticationInfo authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo.getUsername(), "Proper authentication request is not properly " + + "authenticated by the JWTAuthenticator"); + } + + @Test(description = "This method tests the authenticate method under failure conditions") + public void testAuthentiateFailureScenarios() throws NoSuchFieldException, IllegalAccessException { + Request request = createJWTRequest("test", ""); + AuthenticationInfo authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertNull(authenticationInfo.getUsername(), "Un-authenticated request contain username"); + + request = createJWTRequest(jwtToken, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertNull(authenticationInfo.getUsername(), "Un-authenticated request contain username"); + + properties = new Properties(); + properties.setProperty(ISSUER, "test"); + jwtAuthenticator.setProperties(properties); + request = createJWTRequest(jwtToken, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertEquals(authenticationInfo.getStatus(), WebappAuthenticator.Status.FAILURE, + "Un authenticated request does not contain status as failure"); + + properties = new Properties(); + properties.setProperty(ISSUER, ALIAS); + jwtAuthenticator.setProperties(properties); + + request = createJWTRequest(wrongJwtToken, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertEquals(authenticationInfo.getStatus(), WebappAuthenticator.Status.FAILURE, + "Un authenticated request does not contain status as failure"); + + request = createJWTRequest(jwtTokenWithWrongUser, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertEquals(authenticationInfo.getStatus(), WebappAuthenticator.Status.FAILURE, + "Un authenticated request does not contain status as failure"); + } + + + /** + * To create a JWT request with the given jwt header. + * @param jwtToken JWT token to be added to the header + * @param requestUri Request URI to be added to the request. + */ + private Request createJWTRequest(String jwtToken, String requestUri) + throws IllegalAccessException, NoSuchFieldException { Request request = new Request(); org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request(); MimeHeaders mimeHeaders = new MimeHeaders(); @@ -98,12 +172,12 @@ public class JWTAuthenticatorTest { Field uriMB = org.apache.coyote.Request.class.getDeclaredField("uriMB"); uriMB.setAccessible(true); bytes = MessageBytes.newInstance(); - bytes.setString("test"); + bytes.setString(requestUri); uriMB.set(coyoteRequest, bytes); request.setCoyoteRequest(coyoteRequest); - AuthenticationInfo authenticationInfo = jwtAuthenticator.authenticate(request, null); - Assert.assertNotNull(authenticationInfo.getUsername(), "Proper authentication request is not properly " - + "authenticated by the JWTAuthenticator"); + return request; } + + } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponentTest.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponentTest.java new file mode 100644 index 00000000000..a3a06039ec6 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponentTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.webapp.authenticator.framework.internal; + +import org.apache.sling.testing.mock.osgi.MockOsgi; +import org.testng.annotations.Test; + +/** + * This is a test class for {@link WebappAuthenticatorFrameworkServiceComponent} + */ +public class WebappAuthenticatorFrameworkServiceComponentTest { + + @Test(description = "This method tests whether the bundle activator does not throw any exceptions, even under " + + "possible exception scenarios") + public void testActivateWithException() { + WebappAuthenticatorFrameworkServiceComponent webappAuthenticatorFrameworkServiceComponent = new + WebappAuthenticatorFrameworkServiceComponent(); + webappAuthenticatorFrameworkServiceComponent.activate(null); + } + + @Test(description = "This method tests whether bundle activation succeed with the proper confitions.") + public void testActivateWithoutExceptions() { + WebappAuthenticatorFrameworkServiceComponent webappAuthenticatorFrameworkServiceComponent = new + WebappAuthenticatorFrameworkServiceComponent(); + webappAuthenticatorFrameworkServiceComponent.activate(MockOsgi.newComponentContext()); + } +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml index 21430713793..adc6b26287d 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml @@ -22,7 +22,7 @@ - + @@ -32,6 +32,7 @@ + diff --git a/pom.xml b/pom.xml index 5e2e6c6686f..7b2777a5405 100644 --- a/pom.xml +++ b/pom.xml @@ -1568,6 +1568,12 @@ + + org.slf4j + slf4j-nop + test + ${slf4j.nop.version} + @@ -2005,6 +2011,7 @@ 1.0b3 1.7.0 1.4.0.wso2v1 + 1.7.25