Skip to content

Commit

Permalink
SECOAUTH-337: do not issue refresh token if client not authorized
Browse files Browse the repository at this point in the history
  • Loading branch information
dsyer committed Oct 1, 2012
1 parent 0db9a0b commit 373fbb6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
/*
* Copyright 2008 Web Cohesion
*
* 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.
*
* 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.
*/

package org.springframework.security.oauth2.provider.token;
Expand Down Expand Up @@ -86,8 +83,7 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication)
tokenStore.removeRefreshToken(refreshToken);
}
tokenStore.removeAccessToken(existingAccessToken);
}
else {
} else {
return existingAccessToken;
}
}
Expand Down Expand Up @@ -164,8 +160,7 @@ private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication
if (originalScope == null || !originalScope.containsAll(scope)) {
throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope
+ ".", originalScope);
}
else {
} else {
narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication());
}
}
Expand All @@ -189,8 +184,7 @@ public OAuth2Authentication loadAuthentication(String accessTokenValue) throws A
OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue);
if (accessToken == null) {
throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
}
else if (accessToken.isExpired()) {
} else if (accessToken.isExpired()) {
tokenStore.removeAccessToken(accessToken);
throw new InvalidTokenException("Access token expired: " + accessTokenValue);
}
Expand Down Expand Up @@ -232,7 +226,7 @@ public boolean revokeToken(String tokenValue) {
}

private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
if (!supportRefreshToken) {
if (!isSupportRefreshToken(authentication.getAuthorizationRequest())) {
return null;
}
int validitySeconds = getRefreshTokenValiditySeconds(authentication.getAuthorizationRequest());
Expand Down Expand Up @@ -285,6 +279,20 @@ protected int getRefreshTokenValiditySeconds(AuthorizationRequest authorizationR
return refreshTokenValiditySeconds;
}

/**
* Is a refresh token supported for this client (or the global setting if
* {@link #setClientDetailsService(ClientDetailsService) clientDetailsService} is not set.
* @param authorizationRequest the current authorization request
* @return boolean to indicate if refresh token is supported
*/
protected boolean isSupportRefreshToken(AuthorizationRequest authorizationRequest) {
if (clientDetailsService != null) {
ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId());
return client.getAuthorizedGrantTypes().contains("refresh_token");
}
return this.supportRefreshToken;
}

/**
* An access token enhancer that will be applied to a new token before it is saved in the token store.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;

Expand Down Expand Up @@ -129,6 +130,7 @@ public void testClientSpecificRefreshTokenExpiry() throws Exception {
public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception {
BaseClientDetails client = new BaseClientDetails();
client.setRefreshTokenValiditySeconds(100);
client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token"));
return client;
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;

Expand All @@ -22,7 +24,6 @@
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.test.util.ReflectionTestUtils;


/**
* @author Ryan Heaton
* @author Dave Syer
Expand All @@ -31,38 +32,39 @@
public class TestDefaultTokenServicesWithInMemory extends AbstractTestDefaultTokenServices {

private InMemoryTokenStore tokenStore;

@Rule
public ExpectedException expected = ExpectedException.none();

@Test
public void testExpiredToken() throws Exception {
OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id",
Collections.singleton("read")), new TestAuthentication("test2", false));
DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices()
.createAccessToken(expectedAuthentication);
DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken(
expectedAuthentication);
// Make it expire (and rely on mutable state in volatile token store)
firstAccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000));
expected.expect(InvalidTokenException.class);
expected.expectMessage("expired");
getTokenServices().loadAuthentication(firstAccessToken.getValue());
}

@Test
public void testExpiredRefreshToken() throws Exception {
OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id",
Collections.singleton("read")), new TestAuthentication("test2", false));
DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices()
.createAccessToken(expectedAuthentication);
DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken(
expectedAuthentication);
assertNotNull(firstAccessToken.getRefreshToken());
// Make it expire (and rely on mutable state in volatile token store)
ReflectionTestUtils.setField(firstAccessToken.getRefreshToken(), "expiration", new Date(System.currentTimeMillis() - 1000));
ReflectionTestUtils.setField(firstAccessToken.getRefreshToken(), "expiration",
new Date(System.currentTimeMillis() - 1000));
firstAccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000));
expected.expect(InvalidTokenException.class);
expected.expectMessage("refresh token (expired)");
getTokenServices().refreshAccessToken(firstAccessToken.getRefreshToken().getValue(), null);
}

@Test
public void testDifferentRefreshTokenMaintainsState() throws Exception {
// create access token
Expand All @@ -71,13 +73,14 @@ public void testDifferentRefreshTokenMaintainsState() throws Exception {
public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception {
BaseClientDetails client = new BaseClientDetails();
client.setAccessTokenValiditySeconds(1);
client.setAuthorizedGrantTypes(Arrays.asList("authorization_code", "refresh_token"));
return client;
}
});
OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id",
Collections.singleton("read")), new TestAuthentication("test2", false));
DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices()
.createAccessToken(expectedAuthentication);
DefaultOAuth2AccessToken firstAccessToken = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken(
expectedAuthentication);
OAuth2RefreshToken expectedExpiringRefreshToken = firstAccessToken.getRefreshToken();
// Make it expire (and rely on mutable state in volatile token store)
firstAccessToken.setExpiration(new Date(System.currentTimeMillis() - 1000));
Expand All @@ -88,11 +91,30 @@ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exceptio
assertEquals("The new access token should have the same refresh token",
expectedExpiringRefreshToken.getValue(), secondAccessToken.getRefreshToken().getValue());
// refresh access token with refresh token
getTokenServices().refreshAccessToken(expectedExpiringRefreshToken.getValue(), expectedAuthentication
.getAuthorizationRequest().getScope());
getTokenServices().refreshAccessToken(expectedExpiringRefreshToken.getValue(),
expectedAuthentication.getAuthorizationRequest().getScope());
assertEquals(1, getAccessTokenCount());
}

@Test
public void testNoRefreshTokenIfNotAuthorized() throws Exception {
// create access token
getTokenServices().setAccessTokenValiditySeconds(1);
getTokenServices().setClientDetailsService(new ClientDetailsService() {
public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception {
BaseClientDetails client = new BaseClientDetails();
client.setAccessTokenValiditySeconds(1);
client.setAuthorizedGrantTypes(Arrays.asList("authorization_code"));
return client;
}
});
OAuth2Authentication expectedAuthentication = new OAuth2Authentication(new DefaultAuthorizationRequest("id",
Collections.singleton("read")), new TestAuthentication("test2", false));
DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) getTokenServices().createAccessToken(
expectedAuthentication);
assertNull(token.getRefreshToken());
}

@Override
protected TokenStore createTokenStore() {
tokenStore = new InMemoryTokenStore();
Expand All @@ -107,6 +129,6 @@ protected int getAccessTokenCount() {
@Override
protected int getRefreshTokenCount() {
return tokenStore.getRefreshTokenCount();
}
}

}

0 comments on commit 373fbb6

Please sign in to comment.