View Javadoc
1   package org.springframework.security.oauth2.provider.token;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertNotSame;
5   
6   import java.util.Collections;
7   import java.util.Map;
8   
9   import org.junit.Test;
10  import org.springframework.security.jwt.JwtHelper;
11  import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
12  import org.springframework.security.oauth2.common.OAuth2AccessToken;
13  import org.springframework.security.oauth2.common.util.JsonParser;
14  import org.springframework.security.oauth2.common.util.JsonParserFactory;
15  import org.springframework.security.oauth2.provider.OAuth2Authentication;
16  import org.springframework.security.oauth2.provider.TokenRequest;
17  import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
18  import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
19  
20  /**
21   * @author Ryan Heaton
22   * @author Dave Syer
23   * 
24   */
25  public class DefaultTokenServicesWithJwtTests extends AbstractDefaultTokenServicesTests {
26  
27  	private JwtTokenStore tokenStore;
28  	JwtAccessTokenConverter enhancer = new JwtAccessTokenConverter();
29  
30  	@Override
31  	protected TokenStore createTokenStore() {
32  		tokenStore = new JwtTokenStore(enhancer);
33  		return tokenStore;
34  	}
35  
36  	@Override
37  	protected void configureTokenServices(DefaultTokenServices services) throws Exception {
38  		enhancer.afterPropertiesSet();
39  		services.setTokenEnhancer(enhancer);
40  		super.configureTokenServices(services);
41  	}
42  
43  	@Test
44  	public void testRefreshedTokenHasIdThatMatchesAccessToken() throws Exception {
45  		JsonParser parser = JsonParserFactory.create();
46  		OAuth2Authentication authentication = createAuthentication();
47  		OAuth2AccessToken initialToken = getTokenServices().createAccessToken(
48  				authentication);
49  		ExpiringOAuth2RefreshToken expectedExpiringRefreshToken = (ExpiringOAuth2RefreshToken) initialToken
50  				.getRefreshToken();
51  		TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap(
52  				"client_id", "id"), "id", null, null);
53  		OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken(
54  				expectedExpiringRefreshToken.getValue(), tokenRequest);
55  		Map<String, ?> accessTokenInfo = parser.parseMap(JwtHelper.decode(
56  				refreshedAccessToken.getValue()).getClaims());
57  		Map<String, ?> refreshTokenInfo = parser.parseMap(JwtHelper.decode(
58  				refreshedAccessToken.getRefreshToken().getValue()).getClaims());
59  		assertEquals("Access token ID does not match refresh token ATI",
60  				accessTokenInfo.get(AccessTokenConverter.JTI),
61  				refreshTokenInfo.get(AccessTokenConverter.ATI));
62  		assertNotSame("Refresh token re-used", expectedExpiringRefreshToken.getValue(),
63  				refreshedAccessToken.getRefreshToken().getValue());
64  	}
65  
66  	@Test
67  	public void testDoubleRefresh() throws Exception {
68  		JsonParser parser = JsonParserFactory.create();
69  		OAuth2Authentication authentication = createAuthentication();
70  		OAuth2AccessToken initialToken = getTokenServices().createAccessToken(
71  				authentication);
72  		TokenRequest tokenRequest = new TokenRequest(Collections.singletonMap(
73  				"client_id", "id"), "id", null, null);
74  		OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken(
75  				initialToken.getRefreshToken().getValue(), tokenRequest);
76  		refreshedAccessToken = getTokenServices().refreshAccessToken(
77  				refreshedAccessToken.getRefreshToken().getValue(), tokenRequest);
78  		Map<String, ?> accessTokenInfo = parser.parseMap(JwtHelper.decode(
79  				refreshedAccessToken.getValue()).getClaims());
80  		Map<String, ?> refreshTokenInfo = parser.parseMap(JwtHelper.decode(
81  				refreshedAccessToken.getRefreshToken().getValue()).getClaims());
82  		assertEquals("Access token ID does not match refresh token ATI",
83  				accessTokenInfo.get(AccessTokenConverter.JTI),
84  				refreshTokenInfo.get(AccessTokenConverter.ATI));
85  	}
86  
87  	// gh-1109
88  	@Test
89  	public void testReuseRefreshToken() {
90  		getTokenServices().setReuseRefreshToken(true);
91  
92  		OAuth2Authentication authentication = createAuthentication();
93  		OAuth2AccessToken accessToken = getTokenServices().createAccessToken(authentication);
94  		ExpiringOAuth2RefreshToken refreshToken = (ExpiringOAuth2RefreshToken) accessToken.getRefreshToken();
95  
96  		TokenRequest tokenRequest = new TokenRequest(
97  				Collections.singletonMap("client_id", "id"), "id", null, null);
98  		OAuth2AccessToken refreshedAccessToken = getTokenServices().refreshAccessToken(
99  				refreshToken.getValue(), tokenRequest);
100 
101 		JsonParser parser = JsonParserFactory.create();
102 		Map<String, ?> accessTokenClaims = parser.parseMap(
103 				JwtHelper.decode(refreshedAccessToken.getValue()).getClaims());
104 		Map<String, ?> refreshTokenClaims = parser.parseMap(
105 				JwtHelper.decode(refreshedAccessToken.getRefreshToken().getValue()).getClaims());
106 
107 		assertEquals("Access token ID (JTI) does not match refresh token ATI",
108 				accessTokenClaims.get(AccessTokenConverter.JTI),
109 				refreshTokenClaims.get(AccessTokenConverter.ATI));
110 
111 		Map<String, ?> previousRefreshTokenClaims = parser.parseMap(
112 				JwtHelper.decode(refreshToken.getValue()).getClaims());
113 
114 		// The ATI claim in the refresh token is a reference to the JTI claim in the access token.
115 		// So when an access token is refreshed, the ATI claim in the refresh token needs to be updated
116 		// to the JTI claim in the refreshed access token.
117 		// Therefore, if DefaultTokenServices.reuseRefreshToken == true,
118 		// then all claims in the previous and current refresh token
119 		// should be equal minus the ATI claim
120 		previousRefreshTokenClaims.remove(AccessTokenConverter.ATI);
121 		refreshTokenClaims.remove(AccessTokenConverter.ATI);
122 		assertEquals("Refresh token not re-used", previousRefreshTokenClaims, refreshTokenClaims);
123 	}
124 }