/**
* =============================================================================
*
* 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.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.assertThat;
import static org.hamcrest.core.AnyOf.anyOf;
import static org.hamcrest.core.Is.is;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
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.manager.ProfileEntityManager;
import org.orcid.core.oauth.OrcidOauth2TokenDetailService;
import org.orcid.core.oauth.OrcidOauth2UserAuthentication;
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.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional;
/**
* @author Declan Newman (declan) Date: 20/04/2012
*/
@RunWith(OrcidJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:orcid-core-context.xml" })
public class OrcidTokenStoreServiceTest extends DBUnitTest {
@Resource(name = "orcidTokenStore")
private TokenStore orcidTokenStoreService;
@Resource
private ProfileEntityManager profileEntityManager;
@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", "/data/ClientDetailsEntityData.xml", "/data/OrcidOauth2AuthorisationDetailsData.xml"));
}
@AfterClass
public static void removeDBUnitData() throws Exception {
removeDBUnitData(Arrays.asList("/data/OrcidOauth2AuthorisationDetailsData.xml", "/data/ClientDetailsEntityData.xml", "/data/ProfileEntityData.xml",
"/data/SubjectEntityData.xml", "/data/SecurityQuestionEntityData.xml"));
}
@Test
@Transactional
public void testReadAuthentication() throws Exception {
OAuth2Authentication oAuth2Authentication = orcidTokenStoreService.readAuthentication("persistent-token-2");
assertNotNull(oAuth2Authentication);
OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request();
assertNotNull(oAuth2Request);
Object principal = oAuth2Authentication.getPrincipal();
assertNotNull(principal);
assertTrue(!oAuth2Authentication.isClientOnly());
}
@Test
@Transactional
public void testStoreAccessToken() throws Exception {
String clientId = "4444-4444-4444-4441";
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("some-long-oauth2-token-value-9");
ExpiringOAuth2RefreshToken refreshToken = new DefaultExpiringOAuth2RefreshToken("some-long-oauth2-refresh-value-9", new Date());
token.setRefreshToken(refreshToken);
token.setScope(new HashSet<String>(Arrays.asList("/orcid-bio/read", "/orcid-works/read")));
token.setTokenType("bearer");
token.setExpiration(new Date());
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("client_id", clientId);
parameters.put("state", "read");
parameters.put("scope", "/orcid-profile/write");
parameters.put("redirect_uri", "http://www.google.com/");
parameters.put("response_type", "bearer");
OAuth2Request request = new OAuth2Request(Collections.<String, String> emptyMap(), clientId, Collections.<GrantedAuthority> emptyList(), true, new HashSet<String>(Arrays.asList("/orcid-profile/read-limited")), Collections.<String> emptySet(), null, Collections.<String> emptySet(), Collections.<String, Serializable> emptyMap());
ProfileEntity profileEntity = profileEntityManager.findByOrcid("4444-4444-4444-4444");
OrcidOauth2UserAuthentication userAuthentication = new OrcidOauth2UserAuthentication(profileEntity, true);
OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication);
orcidTokenStoreService.storeAccessToken(token, authentication);
OAuth2AccessToken oAuth2AccessToken = orcidTokenStoreService.readAccessToken("some-long-oauth2-token-value-9");
assertNotNull(oAuth2AccessToken);
}
@Test
public void testReadAccessToken() throws Exception {
OAuth2AccessToken oAuth2AccessToken = orcidTokenStoreService.readAccessToken("some-long-oauth2-token-value-1");
assertNotNull(oAuth2AccessToken);
}
@Test
@Transactional
public void testRemoveAccessToken() throws Exception {
OAuth2AccessToken accessToken = new DefaultOAuth2AccessToken("code3");
orcidTokenStoreService.removeAccessToken(accessToken);
OAuth2AccessToken oAuth2AccessToken = orcidTokenStoreService.readAccessToken("code3");
assertNull(oAuth2AccessToken);
}
@Test
@Transactional
public void testReadAuthenticationForRefreshToken() throws Exception {
OAuth2RefreshToken refreshToken = new DefaultOAuth2RefreshToken("some-long-oauth2-refresh-value-1");
OAuth2Authentication oAuth2Authentication = orcidTokenStoreService.readAuthenticationForRefreshToken(refreshToken);
assertNotNull(oAuth2Authentication);
}
@Test
@Transactional
public void testRemoveRefreshToken() throws Exception {
OAuth2AccessToken token = orcidTokenStoreService.readAccessToken("some-long-oauth2-token-value-3");
orcidTokenStoreService.removeRefreshToken(token.getRefreshToken());
OAuth2RefreshToken refreshToken = orcidTokenStoreService.readRefreshToken("some-long-oauth2-refresh-value-3");
assertNull(refreshToken);
}
@Test
@Transactional
public void testRemoveAccessTokenUsingRefreshToken() throws Exception {
OAuth2AccessToken token = orcidTokenStoreService.readAccessToken("persistent-token-1");
orcidTokenStoreService.removeAccessTokenUsingRefreshToken(token.getRefreshToken());
token = orcidTokenStoreService.readAccessToken("persistent-token-1");
assertNull(token);
}
@Test
@Transactional
public void testGetAccessToken() throws Exception {
String clientId = "4444-4444-4444-4441";
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("client_id", clientId);
parameters.put("state", "read");
parameters.put("scope", "/orcid-profile/write");
parameters.put("redirect_uri", "http://www.google.com/");
parameters.put("response_type", "bearer");
OAuth2Request request = new OAuth2Request(Collections.<String, String> emptyMap(), clientId, Collections.<GrantedAuthority> emptyList(), true, new HashSet<String>(Arrays.asList("/orcid-profile/read-limited")), Collections.<String> emptySet(), null, Collections.<String> emptySet(), Collections.<String, Serializable> emptyMap());
ProfileEntity profileEntity = profileEntityManager.findByOrcid("4444-4444-4444-4444");
OrcidOauth2UserAuthentication userAuthentication = new OrcidOauth2UserAuthentication(profileEntity, true);
OAuth2Authentication authentication = new OAuth2Authentication(request, userAuthentication);
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("4444-4444-4444-4441");
token.setExpiration(new Date());
token.setScope(OAuth2Utils.parseParameterList("/orcid-profile/read,/orcid-profile/write"));
token.setTokenType("bearer");
token.setRefreshToken(new DefaultExpiringOAuth2RefreshToken("a-refresh-token", new Date()));
orcidTokenStoreService.storeAccessToken(token, authentication);
OAuth2AccessToken accessToken = orcidTokenStoreService.getAccessToken(authentication);
assertNotNull(accessToken);
}
@Test
public void testFindTokensByUserName() throws Exception {
Collection<OAuth2AccessToken> tokensByUserName = orcidTokenStoreService.findTokensByClientIdAndUserName("4444-4444-4444-4441", "4444-4444-4444-4441");
assertNotNull(tokensByUserName);
assertEquals(1, tokensByUserName.size());
}
@Test
public void testFindTokensByClientId() throws Exception {
Collection<OAuth2AccessToken> tokensByClientId = orcidTokenStoreService.findTokensByClientId("4444-4444-4444-4441");
assertNotNull(tokensByClientId);
assertEquals(1, tokensByClientId.size());
}
@Test
public void testDisabledTokensAreNotReturnedWhenLookingByClientAndUserName() {
String clientId = "4444-4444-4444-4441";
String userId = "0000-0000-0000-0001";
OrcidOauth2TokenDetail token1 = createAccessToken("enabled-1", "/read-limited", clientId, userId, false);
assertNotNull(token1);
assertNotNull(token1.getId());
OrcidOauth2TokenDetail token2 = createAccessToken("enabled-2", "/read-limited", clientId, userId, false);
assertNotNull(token2);
assertNotNull(token2.getId());
OrcidOauth2TokenDetail token3 = createAccessToken("enabled-3", "/read-limited", clientId, userId, false);
assertNotNull(token3);
assertNotNull(token3.getId());
OrcidOauth2TokenDetail disabledToken1 = createAccessToken("disabled-1", "/read-limited", clientId, userId, true);
assertNotNull(disabledToken1);
assertNotNull(disabledToken1.getId());
OrcidOauth2TokenDetail disabledToken2 = createAccessToken("disabled-2", "/read-limited", clientId, userId, true);
assertNotNull(disabledToken2);
assertNotNull(disabledToken2.getId());
OrcidOauth2TokenDetail disabledToken3 = createAccessToken("disabled-3", "/read-limited", clientId, userId, true);
assertNotNull(disabledToken3);
assertNotNull(disabledToken3.getId());
Collection<OAuth2AccessToken> tokens = orcidTokenStoreService.findTokensByClientIdAndUserName(clientId, userId);
assertNotNull(tokens);
assertEquals(3, tokens.size());
for(OAuth2AccessToken token : tokens) {
assertThat(token.getValue(), anyOf(is("enabled-1"), is("enabled-2"), is("enabled-3")));
}
}
private OrcidOauth2TokenDetail createAccessToken(String tokenValue, String scope, String clientId, String userOrcid, boolean disabled) {
OrcidOauth2TokenDetail token = new OrcidOauth2TokenDetail();
token.setApproved(true);
token.setClientDetailsId(clientId);
token.setDateCreated(new Date());
token.setProfile(new ProfileEntity(userOrcid));
token.setScope(scope);
token.setTokenDisabled(disabled);
token.setTokenValue(tokenValue);
orcidOauth2TokenDetailService.saveOrUpdate(token);
return token;
}
}