/* * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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. * * Contributors: * Antoine Taillefer */ package org.nuxeo.ecm.tokenauth; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.test.CoreFeature; import org.nuxeo.ecm.directory.Session; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.ecm.tokenauth.io.AuthenticationToken; import org.nuxeo.ecm.tokenauth.service.TokenAuthenticationService; import org.nuxeo.runtime.test.runner.Features; import org.nuxeo.runtime.test.runner.FeaturesRunner; /** * Tests the {@link TokenAuthenticationService}. * * @author Antoine Taillefer (ataillefer@nuxeo.com) * @since 5.7 */ @RunWith(FeaturesRunner.class) @Features(TokenAuthenticationServiceFeature.class) public class TestTokenAuthenticationService { private static final Log log = LogFactory.getLog(TestTokenAuthenticationService.class); @Inject protected TokenAuthenticationService tokenAuthenticationService; @Inject protected DirectoryService directoryService; @Inject protected CoreFeature coreFeature; @After public void cleanDirectories() throws Exception { try (Session tokenDirSession = directoryService.open("authTokens")) { DocumentModelList entries = tokenDirSession.getEntries(); for (DocumentModel entry : entries) { tokenDirSession.deleteEntry(entry); } } } @Test public void testAcquireToken() { // Test omitting required parameters try { tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", null, null, null); fail("Getting token should have failed since required parameters are missing."); } catch (TokenAuthenticationException e) { assertEquals( "The following parameters are mandatory to get an authentication token: userName, applicationName, deviceId.", e.getMessage()); } // Test token generation String token = tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal box", "rw"); assertNotNull(token); // Test token binding persistence try (Session directorySession = directoryService.open("authTokens")) { DocumentModel tokenModel = directorySession.getEntry(token); assertNotNull(tokenModel); assertEquals(token, tokenModel.getPropertyValue("authtoken:token")); assertEquals("joe", tokenModel.getPropertyValue("authtoken:userName")); assertEquals("myFavoriteApp", tokenModel.getPropertyValue("authtoken:applicationName")); assertEquals("Ubuntu box 64 bits", tokenModel.getPropertyValue("authtoken:deviceId")); assertEquals("This is my personal box", tokenModel.getPropertyValue("authtoken:deviceDescription")); assertEquals("rw", tokenModel.getPropertyValue("authtoken:permission")); assertNotNull(tokenModel.getPropertyValue("authtoken:creationDate")); } // Test existing token acquisition String sameToken = tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal box", "rw"); assertEquals(token, sameToken); // Test token uniqueness String otherToken = tokenAuthenticationService.acquireToken("jack", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal box", "rw"); assertTrue(!otherToken.equals(token)); } @Test public void testGetToken() throws TokenAuthenticationException { // Test non existing token retrieval assertNull(tokenAuthenticationService.getToken("john", "myFavoriteApp", "Ubuntu box 64 bits")); // Test existing token retrieval tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal box", "rw"); assertNotNull(tokenAuthenticationService.getToken("joe", "myFavoriteApp", "Ubuntu box 64 bits")); } @Test public void testGetUserName() throws TokenAuthenticationException { // Test invalid token String token = "invalidToken"; String userName = tokenAuthenticationService.getUserName(token); assertNull(userName); // Test valid token token = tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal box", "rw"); userName = tokenAuthenticationService.getUserName(token); assertEquals("joe", userName); } @Test public void testRevokeToken() throws TokenAuthenticationException { // Test revoking an unexisting token, should not fail tokenAuthenticationService.revokeToken("unexistingToken"); // Test revoking an existing token String token = tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal box", "rw"); assertEquals("joe", tokenAuthenticationService.getUserName(token)); tokenAuthenticationService.revokeToken(token); assertNull(tokenAuthenticationService.getUserName(token)); } @Test public void testGetTokenBindings() { // Test empty token bindings assertEquals(0, tokenAuthenticationService.getTokenBindings("john").size()); // Test existing token bindings String token1 = tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal Linux box", "rw"); log.debug("token1 = " + token1); String token2 = tokenAuthenticationService.acquireToken("joe", "myFavoriteApp", "Windows box 32 bits", "This is my personal Windows box", "rw"); log.debug("token2 = " + token2); String token3 = tokenAuthenticationService.acquireToken("joe", "nuxeoDrive", "Mac OSX VM", "This is my personal Mac box", "rw"); log.debug("token3 = " + token3); DocumentModelList tokenBindings = tokenAuthenticationService.getTokenBindings("joe"); assertEquals(3, tokenBindings.size()); Set<AuthenticationToken> expectedTokenBindings = new HashSet<AuthenticationToken>(); expectedTokenBindings.add(new AuthenticationToken(token1, "joe", "myFavoriteApp", "Ubuntu box 64 bits", "This is my personal Linux box", "rw")); expectedTokenBindings.add(new AuthenticationToken(token2, "joe", "myFavoriteApp", "Windows box 32 bits", "This is my personal Windows box", "rw")); expectedTokenBindings.add(new AuthenticationToken(token3, "joe", "nuxeoDrive", "Mac OSX VM", "This is my personal Mac box", "rw")); assertTrue(CollectionUtils.isEqualCollection(expectedTokenBindings, asAuthenticationTokens(tokenBindings))); for (DocumentModel tokenBinding : tokenBindings) { assertNotNull(tokenBinding.getPropertyValue("authtoken:creationDate")); } } private List<AuthenticationToken> asAuthenticationTokens(DocumentModelList entries) { return entries.stream().map(this::asAuthenticationToken).collect(Collectors.toList()); } private AuthenticationToken asAuthenticationToken(DocumentModel entry) { Map<String, Object> props = entry.getProperties("authtoken"); AuthenticationToken token = new AuthenticationToken( (String) props.get("token"), (String) props.get("userName"), (String) props.get("applicationName"), (String) props.get("deviceId"), (String) props.get("deviceDescription"), (String) props.get("permission")); token.setCreationDate((Calendar) props.get("creationDate")); return token; } }