Merge pull request #34957 from sjohnr

* gh-34957:
  Polish "Add properties to support device grant"
  Add properties to support device grant

Closes gh-34957
pull/35090/head
Andy Wilkinson 2 years ago
commit d2a1fca6b2

@ -99,6 +99,16 @@ public class OAuth2AuthorizationServerProperties implements InitializingBean {
*/ */
private String authorizationUri; private String authorizationUri;
/**
* Authorization Server's OAuth 2.0 Device Authorization Endpoint.
*/
private String deviceAuthorizationUri;
/**
* Authorization Server's OAuth 2.0 Device Verification Endpoint.
*/
private String deviceVerificationUri;
/** /**
* Authorization Server's OAuth 2.0 Token Endpoint. * Authorization Server's OAuth 2.0 Token Endpoint.
*/ */
@ -133,6 +143,22 @@ public class OAuth2AuthorizationServerProperties implements InitializingBean {
this.authorizationUri = authorizationUri; this.authorizationUri = authorizationUri;
} }
public String getDeviceAuthorizationUri() {
return this.deviceAuthorizationUri;
}
public void setDeviceAuthorizationUri(String deviceAuthorizationUri) {
this.deviceAuthorizationUri = deviceAuthorizationUri;
}
public String getDeviceVerificationUri() {
return this.deviceVerificationUri;
}
public void setDeviceVerificationUri(String deviceVerificationUri) {
this.deviceVerificationUri = deviceVerificationUri;
}
public String getTokenUri() { public String getTokenUri() {
return this.tokenUri; return this.tokenUri;
} }
@ -430,6 +456,11 @@ public class OAuth2AuthorizationServerProperties implements InitializingBean {
*/ */
private String accessTokenFormat; private String accessTokenFormat;
/**
* Time-to-live for a device code.
*/
private Duration deviceCodeTimeToLive = Duration.ofMinutes(5);
/** /**
* Whether refresh tokens are reused or a new refresh token is issued when * Whether refresh tokens are reused or a new refresh token is issued when
* returning the access token response. * returning the access token response.
@ -470,6 +501,14 @@ public class OAuth2AuthorizationServerProperties implements InitializingBean {
this.accessTokenFormat = accessTokenFormat; this.accessTokenFormat = accessTokenFormat;
} }
public Duration getDeviceCodeTimeToLive() {
return this.deviceCodeTimeToLive;
}
public void setDeviceCodeTimeToLive(Duration deviceCodeTimeToLive) {
this.deviceCodeTimeToLive = deviceCodeTimeToLive;
}
public boolean isReuseRefreshTokens() { public boolean isReuseRefreshTokens() {
return this.reuseRefreshTokens; return this.reuseRefreshTokens;
} }

@ -53,6 +53,8 @@ final class OAuth2AuthorizationServerPropertiesMapper {
AuthorizationServerSettings.Builder builder = AuthorizationServerSettings.builder(); AuthorizationServerSettings.Builder builder = AuthorizationServerSettings.builder();
map.from(this.properties::getIssuer).to(builder::issuer); map.from(this.properties::getIssuer).to(builder::issuer);
map.from(endpoint::getAuthorizationUri).to(builder::authorizationEndpoint); map.from(endpoint::getAuthorizationUri).to(builder::authorizationEndpoint);
map.from(endpoint::getDeviceAuthorizationUri).to(builder::deviceAuthorizationEndpoint);
map.from(endpoint::getDeviceVerificationUri).to(builder::deviceVerificationEndpoint);
map.from(endpoint::getTokenUri).to(builder::tokenEndpoint); map.from(endpoint::getTokenUri).to(builder::tokenEndpoint);
map.from(endpoint::getJwkSetUri).to(builder::jwkSetEndpoint); map.from(endpoint::getJwkSetUri).to(builder::jwkSetEndpoint);
map.from(endpoint::getTokenRevocationUri).to(builder::tokenRevocationEndpoint); map.from(endpoint::getTokenRevocationUri).to(builder::tokenRevocationEndpoint);
@ -111,6 +113,7 @@ final class OAuth2AuthorizationServerPropertiesMapper {
map.from(token::getAuthorizationCodeTimeToLive).to(builder::authorizationCodeTimeToLive); map.from(token::getAuthorizationCodeTimeToLive).to(builder::authorizationCodeTimeToLive);
map.from(token::getAccessTokenTimeToLive).to(builder::accessTokenTimeToLive); map.from(token::getAccessTokenTimeToLive).to(builder::accessTokenTimeToLive);
map.from(token::getAccessTokenFormat).as(OAuth2TokenFormat::new).to(builder::accessTokenFormat); map.from(token::getAccessTokenFormat).as(OAuth2TokenFormat::new).to(builder::accessTokenFormat);
map.from(token::getDeviceCodeTimeToLive).to(builder::deviceCodeTimeToLive);
map.from(token::isReuseRefreshTokens).to(builder::reuseRefreshTokens); map.from(token::isReuseRefreshTokens).to(builder::reuseRefreshTokens);
map.from(token::getRefreshTokenTimeToLive).to(builder::refreshTokenTimeToLive); map.from(token::getRefreshTokenTimeToLive).to(builder::refreshTokenTimeToLive);
map.from(token::getIdTokenSignatureAlgorithm) map.from(token::getIdTokenSignatureAlgorithm)

@ -124,6 +124,8 @@ class OAuth2AuthorizationServerAutoConfigurationTests {
this.contextRunner this.contextRunner
.withPropertyValues(PROPERTIES_PREFIX + ".issuer=https://example.com", .withPropertyValues(PROPERTIES_PREFIX + ".issuer=https://example.com",
PROPERTIES_PREFIX + ".endpoint.authorization-uri=/authorize", PROPERTIES_PREFIX + ".endpoint.authorization-uri=/authorize",
PROPERTIES_PREFIX + ".endpoint.device-authorization-uri=/device_authorization",
PROPERTIES_PREFIX + ".endpoint.device-verification-uri=/device_verification",
PROPERTIES_PREFIX + ".endpoint.token-uri=/token", PROPERTIES_PREFIX + ".endpoint.jwk-set-uri=/jwks", PROPERTIES_PREFIX + ".endpoint.token-uri=/token", PROPERTIES_PREFIX + ".endpoint.jwk-set-uri=/jwks",
PROPERTIES_PREFIX + ".endpoint.token-revocation-uri=/revoke", PROPERTIES_PREFIX + ".endpoint.token-revocation-uri=/revoke",
PROPERTIES_PREFIX + ".endpoint.token-introspection-uri=/introspect", PROPERTIES_PREFIX + ".endpoint.token-introspection-uri=/introspect",
@ -134,6 +136,8 @@ class OAuth2AuthorizationServerAutoConfigurationTests {
AuthorizationServerSettings settings = context.getBean(AuthorizationServerSettings.class); AuthorizationServerSettings settings = context.getBean(AuthorizationServerSettings.class);
assertThat(settings.getIssuer()).isEqualTo("https://example.com"); assertThat(settings.getIssuer()).isEqualTo("https://example.com");
assertThat(settings.getAuthorizationEndpoint()).isEqualTo("/authorize"); assertThat(settings.getAuthorizationEndpoint()).isEqualTo("/authorize");
assertThat(settings.getDeviceAuthorizationEndpoint()).isEqualTo("/device_authorization");
assertThat(settings.getDeviceVerificationEndpoint()).isEqualTo("/device_verification");
assertThat(settings.getTokenEndpoint()).isEqualTo("/token"); assertThat(settings.getTokenEndpoint()).isEqualTo("/token");
assertThat(settings.getJwkSetEndpoint()).isEqualTo("/jwks"); assertThat(settings.getJwkSetEndpoint()).isEqualTo("/jwks");
assertThat(settings.getTokenRevocationEndpoint()).isEqualTo("/revoke"); assertThat(settings.getTokenRevocationEndpoint()).isEqualTo("/revoke");

@ -66,6 +66,7 @@ class OAuth2AuthorizationServerPropertiesMapperTests {
assertThat(registeredClient.getTokenSettings().getAccessTokenFormat()).isEqualTo(OAuth2TokenFormat.REFERENCE); assertThat(registeredClient.getTokenSettings().getAccessTokenFormat()).isEqualTo(OAuth2TokenFormat.REFERENCE);
assertThat(registeredClient.getTokenSettings().getAccessTokenTimeToLive()).isEqualTo(Duration.ofSeconds(300)); assertThat(registeredClient.getTokenSettings().getAccessTokenTimeToLive()).isEqualTo(Duration.ofSeconds(300));
assertThat(registeredClient.getTokenSettings().getRefreshTokenTimeToLive()).isEqualTo(Duration.ofHours(24)); assertThat(registeredClient.getTokenSettings().getRefreshTokenTimeToLive()).isEqualTo(Duration.ofHours(24));
assertThat(registeredClient.getTokenSettings().getDeviceCodeTimeToLive()).isEqualTo(Duration.ofMinutes(30));
assertThat(registeredClient.getTokenSettings().isReuseRefreshTokens()).isEqualTo(true); assertThat(registeredClient.getTokenSettings().isReuseRefreshTokens()).isEqualTo(true);
assertThat(registeredClient.getTokenSettings().getIdTokenSignatureAlgorithm()) assertThat(registeredClient.getTokenSettings().getIdTokenSignatureAlgorithm())
.isEqualTo(SignatureAlgorithm.RS512); .isEqualTo(SignatureAlgorithm.RS512);
@ -89,6 +90,7 @@ class OAuth2AuthorizationServerPropertiesMapperTests {
token.setAccessTokenFormat("reference"); token.setAccessTokenFormat("reference");
token.setAccessTokenTimeToLive(Duration.ofSeconds(300)); token.setAccessTokenTimeToLive(Duration.ofSeconds(300));
token.setRefreshTokenTimeToLive(Duration.ofHours(24)); token.setRefreshTokenTimeToLive(Duration.ofHours(24));
token.setDeviceCodeTimeToLive(Duration.ofMinutes(30));
token.setReuseRefreshTokens(true); token.setReuseRefreshTokens(true);
token.setIdTokenSignatureAlgorithm("rs512"); token.setIdTokenSignatureAlgorithm("rs512");
return client; return client;
@ -99,6 +101,8 @@ class OAuth2AuthorizationServerPropertiesMapperTests {
this.properties.setIssuer("https://example.com"); this.properties.setIssuer("https://example.com");
OAuth2AuthorizationServerProperties.Endpoint endpoints = this.properties.getEndpoint(); OAuth2AuthorizationServerProperties.Endpoint endpoints = this.properties.getEndpoint();
endpoints.setAuthorizationUri("/authorize"); endpoints.setAuthorizationUri("/authorize");
endpoints.setDeviceAuthorizationUri("/device_authorization");
endpoints.setDeviceVerificationUri("/device_verification");
endpoints.setTokenUri("/token"); endpoints.setTokenUri("/token");
endpoints.setJwkSetUri("/jwks"); endpoints.setJwkSetUri("/jwks");
endpoints.setTokenRevocationUri("/revoke"); endpoints.setTokenRevocationUri("/revoke");
@ -110,6 +114,8 @@ class OAuth2AuthorizationServerPropertiesMapperTests {
AuthorizationServerSettings settings = this.mapper.asAuthorizationServerSettings(); AuthorizationServerSettings settings = this.mapper.asAuthorizationServerSettings();
assertThat(settings.getIssuer()).isEqualTo("https://example.com"); assertThat(settings.getIssuer()).isEqualTo("https://example.com");
assertThat(settings.getAuthorizationEndpoint()).isEqualTo("/authorize"); assertThat(settings.getAuthorizationEndpoint()).isEqualTo("/authorize");
assertThat(settings.getDeviceAuthorizationEndpoint()).isEqualTo("/device_authorization");
assertThat(settings.getDeviceVerificationEndpoint()).isEqualTo("/device_verification");
assertThat(settings.getTokenEndpoint()).isEqualTo("/token"); assertThat(settings.getTokenEndpoint()).isEqualTo("/token");
assertThat(settings.getJwkSetEndpoint()).isEqualTo("/jwks"); assertThat(settings.getJwkSetEndpoint()).isEqualTo("/jwks");
assertThat(settings.getTokenRevocationEndpoint()).isEqualTo("/revoke"); assertThat(settings.getTokenRevocationEndpoint()).isEqualTo("/revoke");

@ -18,6 +18,9 @@ package org.springframework.boot.autoconfigure.security.oauth2.server.servlet;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/** /**
@ -69,4 +72,10 @@ class OAuth2AuthorizationServerPropertiesTests {
.withMessage("Authorization grant types must not be empty."); .withMessage("Authorization grant types must not be empty.");
} }
@Test
void defaultDeviceCodeTimeToLiveMatchesBuilderDefault() {
assertThat(new OAuth2AuthorizationServerProperties.Client().getToken().getDeviceCodeTimeToLive())
.isEqualTo(TokenSettings.builder().build().getDeviceCodeTimeToLive());
}
} }

Loading…
Cancel
Save