/** * ============================================================================= * * ORCID (R) Open Source * http://orcid.org * * Copyright (c) 2012-2014 ORCID, Inc. * Licensed under an MIT-Style License (MIT) * http://orcid.org/open-source-license * * This copyright and license information (including a link to the full license) * shall be included in its entirety in all copies or substantial portion of * the software. * * ============================================================================= */ package org.orcid.core.oauth.service; import static org.hamcrest.core.AllOf.allOf; import static org.hamcrest.core.AnyOf.anyOf; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.annotation.Resource; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.orcid.core.oauth.OrcidOauth2TokenDetailService; import org.orcid.persistence.jpa.entities.OrcidOauth2TokenDetail; import org.orcid.persistence.jpa.entities.ProfileEntity; import org.orcid.test.DBUnitTest; import org.orcid.test.OrcidJUnit4ClassRunner; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.annotation.Transactional; /** * * @author Angel Montenegro */ @RunWith(OrcidJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:orcid-core-context.xml" }) public class OrcidOauth2TokenDetailServiceTest extends DBUnitTest { private static final String CLIENT_ID_1 = "APP-5555555555555555"; private static final String CLIENT_ID_2 = "APP-5555555555555556"; private static final String USER_ORCID = "0000-0000-0000-0001"; @Resource private OrcidOauth2TokenDetailService orcidOauth2TokenDetailService; @BeforeClass public static void initDBUnitData() throws Exception { initDBUnitData(Arrays.asList("/data/SecurityQuestionEntityData.xml", "/data/SubjectEntityData.xml", "/data/SourceClientDetailsEntityData.xml", "/data/ProfileEntityData.xml")); } @AfterClass public static void removeDBUnitData() throws Exception { removeDBUnitData(Arrays.asList("/data/ProfileEntityData.xml", "/data/SourceClientDetailsEntityData.xml", "/data/SubjectEntityData.xml", "/data/SecurityQuestionEntityData.xml")); } @Test @Transactional @Rollback public void dontGetExpiredTokensTest() { //Token # 1: expired createToken(CLIENT_ID_1, "expired-1", USER_ORCID, new Date(System.currentTimeMillis() - 1000), "/read-limited", false); //Token # 2: /activities/update createToken(CLIENT_ID_1, "active-1", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update", false); //Token # 3: disabled createToken(CLIENT_ID_1, "disabled-1", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update", true); //Token # 4: /read-limited createToken(CLIENT_ID_1, "active-2", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited", false); //Fetch all active tokens List<OrcidOauth2TokenDetail> activeTokens = orcidOauth2TokenDetailService.findByUserName(USER_ORCID); assertNotNull(activeTokens); assertEquals(2, activeTokens.size()); assertThat(activeTokens.get(0).getScope(), anyOf(is("/activities/update"), is("/read-limited"))); assertThat(activeTokens.get(1).getScope(), anyOf(is("/activities/update"), is("/read-limited"))); //Find the id of the token with scope '/activities/update' and disable that token Long tokenToDisableId = null; for(OrcidOauth2TokenDetail token : activeTokens) { if("/activities/update".equals(token.getScope())) { tokenToDisableId = token.getId(); break; } } assertNotNull(tokenToDisableId); //Disable that access token orcidOauth2TokenDetailService.disableAccessToken(tokenToDisableId, USER_ORCID); //Fetch the active tokens again, it should contain just one activeTokens = orcidOauth2TokenDetailService.findByUserName(USER_ORCID); assertNotNull(activeTokens); assertEquals(1, activeTokens.size()); assertEquals("/read-limited", activeTokens.get(0).getScope()); assertEquals("active-2", activeTokens.get(0).getTokenValue()); } @Test @Transactional @Rollback public void removeAllTokensWithSameScopesTest() { //We will test deleting this token Long token1Id = createToken(CLIENT_ID_1, "token-1", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update /read-limited", false).getId(); //Delete //Should not delete this Long token2Id = createToken(CLIENT_ID_1, "token-2", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update", false).getId(); //Should not delete this Long token3Id = createToken(CLIENT_ID_1, "token-3", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited", false).getId(); //Should delete this one since it have the same scopes but in different order Long token4Id = createToken(CLIENT_ID_1, "token-4", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited /activities/update", false).getId(); //Delete //Should not delete this since it have one scope more /orcid-profile/read-limited Long token5Id = createToken(CLIENT_ID_1, "token-5", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/orcid-profile/read-limited /activities/update /read-limited", false).getId(); //Should not delete this since it have one scope more /activities/read-limited Long token6Id = createToken(CLIENT_ID_1, "token-6", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited /activities/update /activities/read-limited", false).getId(); //Should not delete this Long token7Id = createToken(CLIENT_ID_1, "token-7", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/person/read-limited", false).getId(); //Should not delete this since it have several more scopes Long token8Id = createToken(CLIENT_ID_1, "token-8", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/funding/read-limited /read-limited /activities/read-limited /orcid-works/create /affiliations/update /activities/update", false).getId(); //Should remove this since it contains the same scopes Long token9Id = createToken(CLIENT_ID_1, "token-9", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update /read-limited", false).getId(); //Delete List<OrcidOauth2TokenDetail> activeTokens = orcidOauth2TokenDetailService.findByUserName(USER_ORCID); assertNotNull(activeTokens); assertEquals(9, activeTokens.size()); orcidOauth2TokenDetailService.disableAccessToken(token1Id, USER_ORCID); activeTokens = orcidOauth2TokenDetailService.findByUserName(USER_ORCID); assertEquals(6, activeTokens.size()); for(OrcidOauth2TokenDetail token : activeTokens) { assertThat(token.getId(), allOf(not(token1Id), not(token4Id), not(token9Id))); assertThat(token.getId(), anyOf(is(token2Id), is(token3Id), is(token5Id), is(token6Id), is(token7Id), is(token8Id))); } } @Test public void dontRemoveOtherClientScopesTest() { Long token1Id = createToken(CLIENT_ID_1, "token-1", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited", false).getId(); //Delete Long token2Id = createToken(CLIENT_ID_1, "token-2", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update", false).getId(); Long token3Id = createToken(CLIENT_ID_1, "token-3", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update /read-limited", false).getId(); Long token4Id = createToken(CLIENT_ID_1, "token-4", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited", false).getId(); //Delete Long token5Id = createToken(CLIENT_ID_2, "token-5", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited", false).getId(); Long token6Id = createToken(CLIENT_ID_2, "token-6", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update", false).getId(); Long token7Id = createToken(CLIENT_ID_2, "token-7", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/activities/update /read-limited", false).getId(); Long token8Id = createToken(CLIENT_ID_2, "token-8", USER_ORCID, new Date(System.currentTimeMillis() + 100000), "/read-limited", false).getId(); List<OrcidOauth2TokenDetail> activeTokens = orcidOauth2TokenDetailService.findByUserName(USER_ORCID); assertNotNull(activeTokens); assertEquals(8, activeTokens.size()); orcidOauth2TokenDetailService.disableAccessToken(token1Id, USER_ORCID); activeTokens = orcidOauth2TokenDetailService.findByUserName(USER_ORCID); assertEquals(6, activeTokens.size()); for(OrcidOauth2TokenDetail token : activeTokens) { assertThat(token.getId(), allOf(not(token1Id), not(token4Id))); assertThat(token.getId(), anyOf(is(token2Id), is(token3Id), is(token5Id), is(token6Id), is(token7Id), is(token8Id))); } } private OrcidOauth2TokenDetail createToken(String clientId, String tokenValue, String userOrcid, Date expirationDate, String scopes, boolean disabled) { OrcidOauth2TokenDetail token = new OrcidOauth2TokenDetail(); token.setApproved(true); token.setClientDetailsId(clientId); token.setDateCreated(new Date()); token.setLastModified(new Date()); token.setProfile(new ProfileEntity(userOrcid)); token.setScope(scopes); token.setTokenDisabled(disabled); token.setTokenExpiration(expirationDate); token.setTokenType("bearer"); token.setTokenValue(tokenValue); orcidOauth2TokenDetailService.saveOrUpdate(token); return token; } }