Refresh token not issued when grant type not configured

Closes gh-155
This commit is contained in:
Laurentiu Spilca 2020-11-28 12:50:12 +02:00 committed by Joe Grandja
parent 7fae37f0b5
commit 7c7e664bb7
5 changed files with 10 additions and 37 deletions

View File

@ -18,6 +18,7 @@ package org.springframework.security.oauth2.server.authorization.authentication;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.OAuth2Error;
@ -126,7 +127,8 @@ public class OAuth2AuthorizationCodeAuthenticationProvider implements Authentica
.accessToken(accessToken); .accessToken(accessToken);
OAuth2RefreshToken refreshToken = null; OAuth2RefreshToken refreshToken = null;
if (registeredClient.getTokenSettings().enableRefreshTokens()) { if (registeredClient.getAuthorizationGrantTypes()
.contains(AuthorizationGrantType.REFRESH_TOKEN)) {
refreshToken = OAuth2TokenIssuerUtil.issueRefreshToken(registeredClient.getTokenSettings().refreshTokenTimeToLive()); refreshToken = OAuth2TokenIssuerUtil.issueRefreshToken(registeredClient.getTokenSettings().refreshTokenTimeToLive());
tokensBuilder.refreshToken(refreshToken); tokensBuilder.refreshToken(refreshToken);
} }
@ -149,4 +151,5 @@ public class OAuth2AuthorizationCodeAuthenticationProvider implements Authentica
public boolean supports(Class<?> authentication) { public boolean supports(Class<?> authentication) {
return OAuth2AuthorizationCodeAuthenticationToken.class.isAssignableFrom(authentication); return OAuth2AuthorizationCodeAuthenticationToken.class.isAssignableFrom(authentication);
} }
} }

View File

@ -31,7 +31,6 @@ import java.util.Map;
public class TokenSettings extends Settings { public class TokenSettings extends Settings {
private static final String TOKEN_SETTING_BASE = "setting.token."; private static final String TOKEN_SETTING_BASE = "setting.token.";
public static final String ACCESS_TOKEN_TIME_TO_LIVE = TOKEN_SETTING_BASE.concat("access-token-time-to-live"); public static final String ACCESS_TOKEN_TIME_TO_LIVE = TOKEN_SETTING_BASE.concat("access-token-time-to-live");
public static final String ENABLE_REFRESH_TOKENS = TOKEN_SETTING_BASE.concat("enable-refresh-tokens");
public static final String REUSE_REFRESH_TOKENS = TOKEN_SETTING_BASE.concat("reuse-refresh-tokens"); public static final String REUSE_REFRESH_TOKENS = TOKEN_SETTING_BASE.concat("reuse-refresh-tokens");
public static final String REFRESH_TOKEN_TIME_TO_LIVE = TOKEN_SETTING_BASE.concat("refresh-token-time-to-live"); public static final String REFRESH_TOKEN_TIME_TO_LIVE = TOKEN_SETTING_BASE.concat("refresh-token-time-to-live");
@ -73,26 +72,6 @@ public class TokenSettings extends Settings {
return this; return this;
} }
/**
* Returns {@code true} if refresh tokens are enabled. The default is {@code true}.
*
* @return {@code true} if refresh tokens are enabled, {@code false} otherwise
*/
public boolean enableRefreshTokens() {
return setting(ENABLE_REFRESH_TOKENS);
}
/**
* Set to {@code true} to enable refresh tokens.
*
* @param enableRefreshTokens {@code true} to enable refresh tokens, {@code false} otherwise
* @return the {@link TokenSettings}
*/
public TokenSettings enableRefreshTokens(boolean enableRefreshTokens) {
setting(ENABLE_REFRESH_TOKENS, enableRefreshTokens);
return this;
}
/** /**
* Returns {@code true} if refresh tokens are reused when returning the access token response, * Returns {@code true} if refresh tokens are reused when returning the access token response,
* or {@code false} if a new refresh token is issued. The default is {@code true}. * or {@code false} if a new refresh token is issued. The default is {@code true}.
@ -138,7 +117,6 @@ public class TokenSettings extends Settings {
protected static Map<String, Object> defaultSettings() { protected static Map<String, Object> defaultSettings() {
Map<String, Object> settings = new HashMap<>(); Map<String, Object> settings = new HashMap<>();
settings.put(ACCESS_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(5)); settings.put(ACCESS_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(5));
settings.put(ENABLE_REFRESH_TOKENS, true);
settings.put(REUSE_REFRESH_TOKENS, true); settings.put(REUSE_REFRESH_TOKENS, true);
settings.put(REFRESH_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(60)); settings.put(REFRESH_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(60));
return settings; return settings;

View File

@ -62,7 +62,6 @@ public class TestRegisteredClients {
.scope("openid") .scope("openid")
.scope("profile") .scope("profile")
.scope("email") .scope("email")
.clientSettings(clientSettings -> clientSettings.requireProofKey(true)) .clientSettings(clientSettings -> clientSettings.requireProofKey(true));
.tokenSettings(tokenSettings -> tokenSettings.enableRefreshTokens(false));
} }
} }

View File

@ -32,9 +32,8 @@ public class TokenSettingsTests {
@Test @Test
public void constructorWhenDefaultThenDefaultsAreSet() { public void constructorWhenDefaultThenDefaultsAreSet() {
TokenSettings tokenSettings = new TokenSettings(); TokenSettings tokenSettings = new TokenSettings();
assertThat(tokenSettings.settings()).hasSize(4); assertThat(tokenSettings.settings()).hasSize(3);
assertThat(tokenSettings.accessTokenTimeToLive()).isEqualTo(Duration.ofMinutes(5)); assertThat(tokenSettings.accessTokenTimeToLive()).isEqualTo(Duration.ofMinutes(5));
assertThat(tokenSettings.enableRefreshTokens()).isTrue();
assertThat(tokenSettings.reuseRefreshTokens()).isTrue(); assertThat(tokenSettings.reuseRefreshTokens()).isTrue();
assertThat(tokenSettings.refreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60)); assertThat(tokenSettings.refreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60));
} }
@ -71,12 +70,6 @@ public class TokenSettingsTests {
.isEqualTo("accessTokenTimeToLive must be greater than Duration.ZERO"); .isEqualTo("accessTokenTimeToLive must be greater than Duration.ZERO");
} }
@Test
public void enableRefreshTokensWhenFalseThenSet() {
TokenSettings tokenSettings = new TokenSettings().enableRefreshTokens(false);
assertThat(tokenSettings.enableRefreshTokens()).isFalse();
}
@Test @Test
public void reuseRefreshTokensWhenFalseThenSet() { public void reuseRefreshTokensWhenFalseThenSet() {
TokenSettings tokenSettings = new TokenSettings().reuseRefreshTokens(false); TokenSettings tokenSettings = new TokenSettings().reuseRefreshTokens(false);
@ -115,9 +108,8 @@ public class TokenSettingsTests {
.<TokenSettings>setting("name1", "value1") .<TokenSettings>setting("name1", "value1")
.accessTokenTimeToLive(accessTokenTimeToLive) .accessTokenTimeToLive(accessTokenTimeToLive)
.<TokenSettings>settings(settings -> settings.put("name2", "value2")); .<TokenSettings>settings(settings -> settings.put("name2", "value2"));
assertThat(tokenSettings.settings()).hasSize(6); assertThat(tokenSettings.settings()).hasSize(5);
assertThat(tokenSettings.accessTokenTimeToLive()).isEqualTo(accessTokenTimeToLive); assertThat(tokenSettings.accessTokenTimeToLive()).isEqualTo(accessTokenTimeToLive);
assertThat(tokenSettings.enableRefreshTokens()).isTrue();
assertThat(tokenSettings.reuseRefreshTokens()).isTrue(); assertThat(tokenSettings.reuseRefreshTokens()).isTrue();
assertThat(tokenSettings.refreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60)); assertThat(tokenSettings.refreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60));
assertThat(tokenSettings.<String>setting("name1")).isEqualTo("value1"); assertThat(tokenSettings.<String>setting("name1")).isEqualTo("value1");

View File

@ -41,13 +41,14 @@ public class AuthorizationServerConfig {
@Bean @Bean
public RegisteredClientRepository registeredClientRepository() { public RegisteredClientRepository registeredClientRepository() {
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("messaging-client") .clientId("client")
.clientSecret("secret") .clientSecret("secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
// .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.redirectUri("http://localhost:8080/authorized") .redirectUri("http://localhost:8080/authorized")
.scope("message.read") .scope("read")
.scope("message.write") .scope("message.write")
.clientSettings(clientSettings -> clientSettings.requireUserConsent(true)) .clientSettings(clientSettings -> clientSettings.requireUserConsent(true))
.build(); .build();