Java tutorial
/** * Copyright 2013 Stockholm County Council * * This file is part of APIGW * * APIGW is free software; you can redistribute it and/or modify * it under the terms of version 2.1 of the GNU Lesser General Public * License as published by the Free Software Foundation. * * APIGW is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with APIGW; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA * */ package org.apigw.authserver.svc.impl; import static org.junit.Assert.*; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import static org.joda.time.DateTime.now; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.junit.Assert; import org.apigw.authserver.svc.ResidentServices; import org.apigw.authserver.svc.TokenServices; import org.apigw.authserver.svc.repository.CertifiedClientPermissionRepository; import org.apigw.authserver.svc.repository.AuthorizationGrantRepository; import org.apigw.authserver.svc.repository.CertifiedClientRepository; import org.apigw.authserver.svc.repository.PermissionRepository; import org.apigw.authserver.types.domain.CertifiedClientPermission; import org.apigw.authserver.types.domain.AuthorizationGrant; import org.apigw.authserver.types.domain.CertifiedClient; import org.apigw.authserver.types.domain.Permission; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; /** * This test class contains code derived from the TestRandomValueTokenServices * class in Spring Security OAuth 2.0 licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). * TestRandomValueTokenServices class in Spring Security OAuth 2.0 * was originally written by Ryan Heaton and Dave Syer and the original * code is changed by Christian Hilmersson in this class. * See Spring Security OAuth at Github for more information: * https://github.com/SpringSource/spring-security-oauth/ * * @author Christian Hilmersson * */ @RunWith(SpringJUnit4ClassRunner.class) @TransactionConfiguration(defaultRollback = true) @ContextConfiguration(locations = "classpath:apigw-resources-test-config.xml") public class TokenServicesImplTest { @Autowired private TokenServices services; @Autowired private AuthorizationGrantRepository authorizationGrantRepository; @Autowired private CertifiedClientPermissionRepository ccPermissionRepository; @Autowired private PermissionRepository permRepository; @Autowired private CertifiedClientRepository certifiedClientRepository; final DateTimeFormatter yyyyMMddFormatter = DateTimeFormat.forPattern("yyyyMMdd"); private static final String CLIENT = "client"; private static final String READ_SCOPE = "SCOPE_READ_SCHEDULE"; private static final String WRITE_SCOPE = "SCOPE_WRITE_SCHEDULE"; // private static final String CITIZEN = "630928-3221"; // private static final String LEGAL_GUARDIAN = "188803099368"; @After public void removeStore() { authorizationGrantRepository.deleteAll(); ccPermissionRepository.deleteAll(); permRepository.deleteAll(); certifiedClientRepository.deleteAll(); } @Before public void createStore() throws Exception { CertifiedClient client = new CertifiedClient(); client.setClientId(CLIENT); client.setName("name"); client.setX509CertificateIssuerDN("issuerDN"); client.setX509CertificateSubjectDN("subjectDN"); certifiedClientRepository.save(client); Permission perm1 = new Permission(); perm1.setName(READ_SCOPE); perm1.setAccessTokenValiditySeconds(30 * 24 * 3600); permRepository.save(perm1); Permission perm2 = new Permission(); perm2.setName(WRITE_SCOPE); perm2.setAccessTokenValiditySeconds(3600); permRepository.save(perm2); CertifiedClientPermission asRole1 = new CertifiedClientPermission(); asRole1.setCertifiedClient(client); asRole1.setPermission(perm1); ccPermissionRepository.save(asRole1); CertifiedClientPermission asRole2 = new CertifiedClientPermission(); asRole2.setCertifiedClient(client); asRole2.setPermission(perm2); ccPermissionRepository.save(asRole2); services.setSupportRefreshToken(false); } private Date createDate(int year, int month, int day, int hour, int minute) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, day, hour, minute); return calendar.getTime(); } private AuthorizationGrant buildAuthorizationGrantWithLegalGuardian() { final AuthorizationGrant authorizationGrant = buildAuthorizationGrant(); authorizationGrant.setLegalGuardianResidentIdentificationNumber("111111-1111"); return authorizationGrant; } private AuthorizationGrant buildAuthorizationGrant() { return buildAuthorizationGrant("121212-1212"); } private AuthorizationGrant buildAuthorizationGrant(String residentIdentificationNumber) { Permission scopeReadSchedule = new Permission(); scopeReadSchedule.setName(READ_SCOPE); Permission scopeWriteSchedule = new Permission(); scopeWriteSchedule.setName(WRITE_SCOPE); CertifiedClientPermission ccPermissionRead = new CertifiedClientPermission(); ccPermissionRead.setPermission(scopeReadSchedule); CertifiedClientPermission ccPermissionWrite = new CertifiedClientPermission(); ccPermissionWrite.setPermission(scopeWriteSchedule); AuthorizationGrant authorizationGrant = new AuthorizationGrant(); authorizationGrant.setGrantedPermissions(Arrays.asList(ccPermissionRead, ccPermissionWrite)); authorizationGrant.setAccessToken("ABC"); authorizationGrant.setAccessTokenExpires(createDate(2012, 5, 2, 16, 30)); authorizationGrant.setClientId(CLIENT); authorizationGrant.setGrantExpires(createDate(2012, 6, 2, 15, 30)); authorizationGrant.setRefreshToken("XYZ"); authorizationGrant.setResidentIdentificationNumber(residentIdentificationNumber); //"121212-1212" authorizationGrant.setVersion(0); return authorizationGrant; } private AuthorizationGrant buildAuthorizationGrantReversedScopes() { Permission scopeReadSchedule = new Permission(); scopeReadSchedule.setName(READ_SCOPE); Permission scopeWriteSchedule = new Permission(); scopeWriteSchedule.setName(WRITE_SCOPE); CertifiedClientPermission ccPermissionRead = new CertifiedClientPermission(); ccPermissionRead.setPermission(scopeReadSchedule); CertifiedClientPermission ccPermissionWrite = new CertifiedClientPermission(); ccPermissionWrite.setPermission(scopeWriteSchedule); AuthorizationGrant authorizationGrant = new AuthorizationGrant(); authorizationGrant.setGrantedPermissions(Arrays.asList(ccPermissionWrite, ccPermissionRead)); authorizationGrant.setAccessToken("ABC"); authorizationGrant.setAccessTokenExpires(createDate(2012, 5, 2, 16, 30)); authorizationGrant.setClientId(CLIENT); authorizationGrant.setGrantExpires(createDate(2012, 6, 2, 15, 30)); authorizationGrant.setRefreshToken("XYZ"); authorizationGrant.setResidentIdentificationNumber("121212-1212"); authorizationGrant.setVersion(0); return authorizationGrant; } /** * Check so that different order of the input scopes gives the same output. */ @Test @DirtiesContext public void testBuildScopeSetFromAuthorizationGrantScopeOrder() { AuthorizationGrant authorizationGrant = buildAuthorizationGrant(); TokenServicesImpl tokenServices = new TokenServicesImpl(); Set<String> scope = tokenServices.buildScopeFromAuthorizationGrant(authorizationGrant); Assert.assertNotNull(scope); Assert.assertEquals(2, scope.size()); Set<String> expectedScopes = new HashSet<String>(Arrays.asList(READ_SCOPE, WRITE_SCOPE)); List<String> listOne = new ArrayList<String>(); for (String actualScope : scope) { Assert.assertTrue(expectedScopes.remove(actualScope)); listOne.add(actualScope); } // Create scope from reversed auth grant with list of scopes authorizationGrant = buildAuthorizationGrantReversedScopes(); scope = tokenServices.buildScopeFromAuthorizationGrant(authorizationGrant); int i = 0; for (String actualScope : scope) { Assert.assertEquals(listOne.get(i), actualScope); i++; } } @Test @DirtiesContext public void testBuildScopeSetFromAuthorizationGrant() { AuthorizationGrant authorizationGrant = buildAuthorizationGrant(); TokenServicesImpl tokenServices = new TokenServicesImpl(); Set<String> scope = tokenServices.buildScopeFromAuthorizationGrant(authorizationGrant); Assert.assertNotNull(scope); Assert.assertEquals(2, scope.size()); Set<String> expectedScopes = new HashSet<String>(Arrays.asList(READ_SCOPE, WRITE_SCOPE)); for (String actualScope : scope) { Assert.assertTrue(expectedScopes.remove(actualScope)); } } @Test @DirtiesContext public void testBuildAuthorizationGrantExpiresCitizenIs12Today() { long validitySeconds = 60 * 60 * 12; DateTime dateOfBirth = now().minusYears(12); String residentIdentificationNumber = yyyyMMddFormatter.print(dateOfBirth) + "-9876"; services.setAccessTokenValiditySeconds(validitySeconds); OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false, residentIdentificationNumber)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); Date expirationDate = accessToken.getExpiration(); // 12 hours from now DateTime expectedDate = now().plus(validitySeconds * 1000L); // check the dates are within one second of each other - assumption is that the unit test runs in less than one second assertTrue("expirationDate:" + expirationDate + " != expectedDate:" + expectedDate, Math.abs(expirationDate.getTime() - expectedDate.getMillis()) < 1000); assertTrue("expires too soon:" + accessToken.getExpiresIn() + " - validitySeconds:" + validitySeconds, accessToken.getExpiresIn() <= validitySeconds); assertTrue("expires too late:" + accessToken.getExpiresIn() + " - validitySeconds:" + validitySeconds, accessToken.getExpiresIn() >= validitySeconds - 1); } @Test @DirtiesContext public void testBuildAuthorizationGrantExpiresCitizenIs18Today() { long validitySeconds = 60 * 60 * 12; // 12 hours DateTime dateOfBirth = now().minusYears(18); String residentIdentificationNumber = yyyyMMddFormatter.print(dateOfBirth) + "-9876"; services.setAccessTokenValiditySeconds(validitySeconds); OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false, residentIdentificationNumber)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); Date expirationDate = accessToken.getExpiration(); // 12 hours from now DateTime expectedDate = now().plus(validitySeconds * 1000L); // check the dates are within one second of each other - assumption is that the unit test runs in less than one second assertTrue("expirationDate:" + expirationDate + " != expectedDate:" + expectedDate, Math.abs(expirationDate.getTime() - expectedDate.getMillis()) < 1000); assertTrue("expires too soon:" + accessToken.getExpiresIn() + " - validitySeconds:" + validitySeconds, accessToken.getExpiresIn() <= validitySeconds); assertTrue("expires too late:" + accessToken.getExpiresIn() + " - validitySeconds:" + validitySeconds, accessToken.getExpiresIn() >= validitySeconds - 1); } @Test @DirtiesContext public void testBuildAuthorizationGrantExpiresCitizenIs13Today() { long validitySeconds = 60 * 60 * 12; // 12 hours DateTime dateOfBirth = now().minusYears(13); String residentIdentificationNumber = yyyyMMddFormatter.print(dateOfBirth) + "-9876"; services.setAccessTokenValiditySeconds(validitySeconds); OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false, residentIdentificationNumber)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); assertTrue("token should be expired", accessToken.isExpired()); } @Test @DirtiesContext public void testBuildAuthorizationGrantExpiresCitizenIs13Tomorrow() { long validitySeconds = 60 * 60 * 48; // 48 hours (use more than one day of expiration so we can make correct assumption about expected expiration) DateTime dateOfBirth = now().minusYears(13).plusDays(1); String residentIdentificationNumber = yyyyMMddFormatter.print(dateOfBirth) + "-9876"; services.setAccessTokenValiditySeconds(validitySeconds); OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false, residentIdentificationNumber)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); Date expirationDate = accessToken.getExpiration(); DateTime expectedDate = now().withTimeAtStartOfDay().plusDays(1); // midnight // check the dates are within one second of each other - assumption is that the unit test runs in less than one second assertTrue("expirationDate:" + expirationDate + " != expectedDate:" + expectedDate, Math.abs(expirationDate.getTime() - expectedDate.getMillis()) < 1000); assertTrue( "expires too soon:" + accessToken.getExpiresIn() + " - seconds to midnight:" + expectedDate.minus(now().getMillis()).getMillis() / 1000L, accessToken.getExpiresIn() <= expectedDate.minus(now().getMillis()).getMillis() / 1000L); assertTrue( "expires too late:" + accessToken.getExpiresIn() + " - seconds to midnight:" + expectedDate.minus(now().getMillis()).getMillis() / 1000L, accessToken.getExpiresIn() >= expectedDate.minus(now().getMillis()).getMillis() / 1000L - 1); } @Test @DirtiesContext public void testBuildAccessTokenFromAuthorizationGrant() { AuthorizationGrant authorizationGrant = buildAuthorizationGrant(); TokenServicesImpl tokenServices = new TokenServicesImpl(); tokenServices.setSupportRefreshToken(true); OAuth2AccessToken accessToken = tokenServices.buildAccessTokenFromAuthorizationGrant(authorizationGrant, true); Assert.assertNotNull(accessToken); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm"); Assert.assertEquals("201205021630", sdf.format(accessToken.getExpiration())); Assert.assertEquals("XYZ", accessToken.getRefreshToken().getValue()); Set<String> scope = accessToken.getScope(); Assert.assertEquals(2, scope.size()); Set<String> expectedScopes = new HashSet<String>(Arrays.asList(READ_SCOPE, WRITE_SCOPE)); for (String actualScope : scope) { Assert.assertTrue(expectedScopes.remove(actualScope)); } Assert.assertEquals(OAuth2AccessToken.BEARER_TYPE, accessToken.getTokenType()); Assert.assertEquals("ABC", accessToken.getValue()); } @Test @DirtiesContext public void testBuildAccessTokenFromAuthorizationGrantWithNoRefreshToken() { AuthorizationGrant authorizationGrant = buildAuthorizationGrant(); TokenServicesImpl tokenServices = new TokenServicesImpl(); tokenServices.setSupportRefreshToken(false); OAuth2AccessToken accessToken = tokenServices.buildAccessTokenFromAuthorizationGrant(authorizationGrant, true); Assert.assertNotNull(accessToken); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm"); Assert.assertEquals("201205021630", sdf.format(accessToken.getExpiration())); Assert.assertNull(accessToken.getRefreshToken()); } private AuthorizationRequest createAuthorizationRequest(String client, Set<String> scope) { DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(client, scope); authorizationRequest.setApproved(true); return authorizationRequest; } @Test @DirtiesContext public void testDoubleStoreToken() throws InterruptedException { OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false)); OAuth2AccessToken token1 = services.createAccessToken(authentication); Thread.sleep(1500); OAuth2AccessToken token2 = services.createAccessToken(authentication); // Make sure we don't get the same access token twice Assert.assertFalse(token1.getValue().equals(token2.getValue())); Assert.assertFalse(token1.getExpiration().equals(token2.getExpiration())); } @Test @DirtiesContext @Ignore public void testConcurrentTokenUpdate() throws InterruptedException { // ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = new ExpiringOAuth2RefreshToken("testToken", new Date( // System.currentTimeMillis() + 100000)); final OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false)); final OAuth2AccessToken[] accessTokens = new OAuth2AccessToken[10]; for (int i = 0; i < 10; i++) { accessTokens[i] = services.createAccessToken(authentication); } int numberOfConcurrent = 1000; List<Thread> executors = new ArrayList<Thread>(); for (int i = 0; i < numberOfConcurrent; i++) { Thread concurrentUpdater = new Thread() { // private OAuth2Authentication innerAuthentication = authentication; // private TransactionalAuthServerTokenServicesDelegatorImpl innerServices = services; @Override public void run() { System.out.println("To run createAccessToken"); try { if (Math.random() > 0.8) { services.createAccessToken(authentication); } else { OAuth2AccessToken tk = accessTokens[(int) Math.floor(Math.random() * 10)]; AuthorizationRequest request = createAuthorizationRequest(CLIENT, tk.getScope()); services.refreshAccessToken(tk.getValue(), request); } } catch (Exception e) { e.printStackTrace(); // Thread.currentThread().interrupt(); // Assert.fail("Got exception: " + e.getMessage()); throw new RuntimeException("failed"); } System.out.println("Ran createAccessToken"); } }; executors.add(concurrentUpdater); } for (Thread executor : executors) { executor.start(); } for (Thread executor : executors) { executor.join(); } Assert.assertEquals(1, authorizationGrantRepository.count()); } @Test @DirtiesContext public void testRefreshedTokenHasScopes() throws Exception { services.setSupportRefreshToken(true); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(expectedAuthentication); AuthorizationRequest request = createAuthorizationRequest(CLIENT, Collections.<String>emptySet()); OAuth2AccessToken refreshedAccessToken = services .refreshAccessToken(accessToken.getRefreshToken().getValue(), request); assertFalse(accessToken.getValue().equals(refreshedAccessToken.getValue())); assertEquals("[" + READ_SCOPE + "]", refreshedAccessToken.getScope().toString()); } @Test @DirtiesContext public void testRefreshedTokenWithNarrowedScope() throws Exception { services.setSupportRefreshToken(true); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE, WRITE_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(expectedAuthentication); assertEquals("[" + READ_SCOPE + ", " + WRITE_SCOPE + "]", accessToken.getScope().toString()); AuthorizationRequest request = createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)); OAuth2AccessToken refreshedAccessToken = services .refreshAccessToken(accessToken.getRefreshToken().getValue(), request); assertEquals("[" + READ_SCOPE + "]", refreshedAccessToken.getScope().toString()); } @Test(expected = InvalidScopeException.class) @DirtiesContext public void testRefreshedTokenWithAnotherScope() throws Exception { services.setSupportRefreshToken(true); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(expectedAuthentication); assertEquals("[" + READ_SCOPE + "]", accessToken.getScope().toString()); AuthorizationRequest request = createAuthorizationRequest(CLIENT, Collections.singleton(WRITE_SCOPE)); services.refreshAccessToken(accessToken.getRefreshToken().getValue(), request); } @Test(expected = InvalidScopeException.class) @DirtiesContext public void testRefreshedTokenOnExistingClientAndScope() throws Exception { services.setSupportRefreshToken(true); OAuth2Authentication firstAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken firstAccessToken = services.createAccessToken(firstAuthentication); assertEquals("[" + READ_SCOPE + "]", firstAccessToken.getScope().toString()); OAuth2Authentication secondAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE, WRITE_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken secondAccessToken = services.createAccessToken(secondAuthentication); assertEquals("[" + READ_SCOPE + ", " + WRITE_SCOPE + "]", secondAccessToken.getScope().toString()); assertEquals(2, authorizationGrantRepository.count()); for (AuthorizationGrant auth : authorizationGrantRepository.findAll()) { System.out.println(auth.getAuthenticationKey()); } AuthorizationRequest request = createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)); services.refreshAccessToken(secondAccessToken.getRefreshToken().getValue(), request); } @Test(expected = InvalidGrantException.class) @DirtiesContext public void testRefreshTokenWithNoSupport() throws Exception { AuthorizationRequest request = createAuthorizationRequest(CLIENT, Collections.singleton(WRITE_SCOPE)); services.refreshAccessToken("token", request); } @Test @DirtiesContext public void testUnlimitedTokenExpiry() throws Exception { services.setAccessTokenValiditySeconds(0); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(expectedAuthentication); assertEquals("[" + READ_SCOPE + "]", accessToken.getScope().toString()); assertEquals(0, accessToken.getExpiresIn()); assertEquals(null, accessToken.getExpiration()); } @Test @DirtiesContext public void testDefaultTokenExpiry() throws Exception { services.setAccessTokenValiditySeconds(100); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(expectedAuthentication); assertTrue(100 >= accessToken.getExpiresIn()); } @Test @DirtiesContext public void testRoleSpecificTokenExpiry() throws Exception { services.setAccessTokenValiditySeconds(100 * 24 * 3600); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(expectedAuthentication); assertTrue(30 * 24 * 3600 >= accessToken.getExpiresIn()); } @Test @DirtiesContext public void testLeastRoleSpecificTokenExpiry() throws Exception { services.setAccessTokenValiditySeconds(100 * 24 * 3600); OAuth2Authentication expectedAuthentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE, WRITE_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(expectedAuthentication); assertTrue(3600 >= accessToken.getExpiresIn()); } @Test @DirtiesContext public void testOneAccessTokenPerAuthentication() throws Exception { OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false)); OAuth2AccessToken first = services.createAccessToken(authentication); assertEquals(1, authorizationGrantRepository.count()); OAuth2AccessToken second = services.createAccessToken(authentication); assertFalse(first.equals(second)); assertEquals(1, authorizationGrantRepository.count()); } @Test @DirtiesContext public void testOneAccessTokenPerUniqueAuthentication() throws Exception { OAuth2AccessToken token1 = services.createAccessToken( new OAuth2Authentication(createAuthorizationRequest(CLIENT, Collections.singleton(READ_SCOPE)), new TestAuthentication(false))); assertEquals(1, authorizationGrantRepository.count()); OAuth2AccessToken token2 = services.createAccessToken( new OAuth2Authentication(createAuthorizationRequest(CLIENT, Collections.singleton(WRITE_SCOPE)), new TestAuthentication(false))); assertEquals(2, authorizationGrantRepository.count()); assertTrue(token1 != token2); } @Test @DirtiesContext public void testCreateAccessTokenWithDifferentOrderedScopes() { OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE, WRITE_SCOPE))), new TestAuthentication(false)); String accessToken = services.createAccessToken(authentication).getValue(); assertNotNull(authorizationGrantRepository.findByAccessToken(accessToken)); authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(WRITE_SCOPE, READ_SCOPE))), new TestAuthentication(false)); services.createAccessToken(authentication); // Now the first access token should have been overwritten with a new one since // they have the same scope, only in different order Assert.assertNull(authorizationGrantRepository.findByAccessToken(accessToken)); } @Test @DirtiesContext public void testLoadAuthentication() throws Exception { AuthorizationGrant auth = buildAuthorizationGrant(); for (CertifiedClientPermission ccPermission : auth.getGrantedPermissions()) { ccPermission.setCertifiedClient(certifiedClientRepository.findOne(0L)); ccPermission.setPermission(permRepository.findOne(0L)); ccPermissionRepository.save(ccPermission); } auth.setAccessTokenExpires(new Date(System.currentTimeMillis() + 10000)); authorizationGrantRepository.save(auth); assertEquals(1, authorizationGrantRepository.count()); OAuth2Authentication storedAuthentication = services.loadAuthentication(auth.getAccessToken()); assertNotNull(storedAuthentication); } @Test public void testLoadAuthenticationWithValidLegalGuardian() throws Exception { final OAuth2Authentication oAuth2Authentication = testLoadAuthenticationWithLegalGuardian(true); assertNotNull(oAuth2Authentication); } @Test(expected = InvalidGrantException.class) public void testLoadAuthenticationWithInvalidLegalGuardian() throws Exception { testLoadAuthenticationWithLegalGuardian(false); } private OAuth2Authentication testLoadAuthenticationWithLegalGuardian(boolean validLegalGuardian) throws Exception { final TokenServicesImpl tokenServices = new TokenServicesImpl(); final AuthorizationGrant auth = buildAuthorizationGrantWithLegalGuardian(); auth.setAccessTokenExpires(new DateTime().plusYears(1).toDate()); final ResidentServices residentServices = mock(ResidentServices.class); final AuthorizationGrantRepository repo = mock(AuthorizationGrantRepository.class); when(repo.findByAccessToken(anyString())).thenReturn(auth); when(residentServices.validateLegalGuardian(anyString(), anyString())).thenReturn(validLegalGuardian); tokenServices.setResidentServices(residentServices); tokenServices.setAuthorizationGrantRepository(repo); return tokenServices.loadAuthentication(auth.getAccessToken()); } @Test @DirtiesContext public void testFindTokensByUsername() { OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); Collection<OAuth2AccessToken> tokens = services.findTokensByUserName("1912121212"); assertEquals(1, tokens.size()); assertEquals(accessToken.getValue(), tokens.iterator().next().getValue()); } @Test public void testFindOnlyValidTokensByUsername() { final TokenServicesImpl tokenServices = new TokenServicesImpl(); final AuthorizationGrant auth = buildAuthorizationGrantWithLegalGuardian(); final ResidentServices residentServices = mock(ResidentServices.class); final AuthorizationGrantRepository repo = mock(AuthorizationGrantRepository.class); tokenServices.setResidentServices(residentServices); tokenServices.setAuthorizationGrantRepository(repo); when(repo.findByResidentIdentificationNumber(anyString())).thenReturn(Collections.nCopies(4, auth)); when(residentServices.validateLegalGuardian(anyString(), anyString())).thenReturn(true, false, false, true); final Collection<OAuth2AccessToken> tokens = tokenServices .findTokensByUserName(auth.getResidentIdentificationNumber()); assertEquals(2, tokens.size()); } @Test @DirtiesContext public void testFindTokensByClientId() { OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); Collection<OAuth2AccessToken> tokens = services.findTokensByClientId(CLIENT); assertEquals(1, tokens.size()); assertEquals(accessToken.getValue(), tokens.iterator().next().getValue()); } @Test(expected = InvalidGrantException.class) @DirtiesContext public void testRevokeToken() { OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); boolean revoked = services.revokeToken(accessToken.getValue()); assertTrue(revoked); services.getAccessToken(authentication); } @Test @DirtiesContext public void testGetClientId() { OAuth2Authentication authentication = new OAuth2Authentication( createAuthorizationRequest(CLIENT, new HashSet<String>(Arrays.asList(READ_SCOPE))), new TestAuthentication(false)); OAuth2AccessToken accessToken = services.createAccessToken(authentication); String clientId = services.getClientId(accessToken.getValue()); assertEquals(CLIENT, clientId); } @Test @DirtiesContext public void buildScopeFromAuthorizationGrant() { TokenServicesImpl servicesImpl = new TokenServicesImpl(); AuthorizationGrant grant = buildAuthorizationGrant(); Set<String> scopes = servicesImpl.buildScopeFromAuthorizationGrant(grant); assertTrue(scopes.contains(READ_SCOPE)); assertTrue(scopes.contains(WRITE_SCOPE)); } protected static class TestAuthentication extends AbstractAuthenticationToken { private static final long serialVersionUID = 1L; private final String principal; public TestAuthentication(boolean authenticated, String residentIdentificationNumber) { super(null); setAuthenticated(authenticated); this.principal = residentIdentificationNumber; } public TestAuthentication(boolean authenticated) { this(authenticated, "1912121212"); } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return this.principal; } } }