From 2083c52f0d32f6ade5e62f6df399c099b7611458 Mon Sep 17 00:00:00 2001 From: strehle Date: Mon, 17 Jul 2023 09:41:23 +0200 Subject: [PATCH 1/3] Change default of refresh token format Default should be opaque, at least the default. History about https://github.com/cloudfoundry/uaa-release/issues/93 Some tests rely on JWT for refresh, therefore added for these tests again jwt.token.refresh.format=jwt --- uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml | 2 +- .../identity/uaa/mock/token/TokenMvcMockTests.java | 2 +- .../identity/uaa/oauth/UaaTokenServicesTests.java | 2 +- uaa/src/test/resources/integration_test_properties.yml | 6 +++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml index 5b262fac55c..85e239cf6f6 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml @@ -498,7 +498,7 @@ + value="${jwt.token.refresh.format:#{T(org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.TokenFormat).OPAQUE.getStringValue()}}"/> diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java index a55a618c95f..1ddce9d92c9 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java @@ -176,7 +176,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@TestPropertySource(properties = {"uaa.url=https://localhost:8080/uaa"}) +@TestPropertySource(properties = {"uaa.url=https://localhost:8080/uaa", "jwt.token.refresh.format=jwt"}) public class TokenMvcMockTests extends AbstractTokenMockMvcTests { private String BADSECRET = "badsecret"; protected RandomValueStringGenerator generator = new RandomValueStringGenerator(); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/oauth/UaaTokenServicesTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/oauth/UaaTokenServicesTests.java index 019224a5632..564f15cde8d 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/oauth/UaaTokenServicesTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/oauth/UaaTokenServicesTests.java @@ -77,7 +77,7 @@ @DisplayName("Uaa Token Services Tests") @DefaultTestContext -@TestPropertySource(properties = {"uaa.url=https://uaa.some.test.domain.com:555/uaa"}) +@TestPropertySource(properties = {"uaa.url=https://uaa.some.test.domain.com:555/uaa", "jwt.token.refresh.format=jwt"}) class UaaTokenServicesTests { @Autowired private UaaTokenServices tokenServices; diff --git a/uaa/src/test/resources/integration_test_properties.yml b/uaa/src/test/resources/integration_test_properties.yml index 36354c7a851..6119405c482 100644 --- a/uaa/src/test/resources/integration_test_properties.yml +++ b/uaa/src/test/resources/integration_test_properties.yml @@ -16,7 +16,11 @@ LOGIN_SECRET: loginsecret jwt: token: signing-key: tokenKey - + revocable: false + refresh: + format: opaque + rotate: false + unique: false login: serviceProviderKey: | -----BEGIN RSA PRIVATE KEY----- From 5f2ea7b82f0c9cf50200fe88b075d5f195bf0833 Mon Sep 17 00:00:00 2001 From: strehle Date: Wed, 26 Jul 2023 10:23:07 +0200 Subject: [PATCH 2/3] more default changes --- .../java/org/cloudfoundry/identity/uaa/zone/TokenPolicy.java | 4 ++-- .../org/cloudfoundry/identity/uaa/zone/TokenPolicyTest.java | 2 +- .../identity/uaa/mock/zones/IdentityZoneEndpointDocs.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/model/src/main/java/org/cloudfoundry/identity/uaa/zone/TokenPolicy.java b/model/src/main/java/org/cloudfoundry/identity/uaa/zone/TokenPolicy.java index fe24d259371..23ab8995793 100644 --- a/model/src/main/java/org/cloudfoundry/identity/uaa/zone/TokenPolicy.java +++ b/model/src/main/java/org/cloudfoundry/identity/uaa/zone/TokenPolicy.java @@ -24,7 +24,7 @@ import java.util.stream.Collector; import java.util.stream.Collectors; -import static org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.TokenFormat.JWT; +import static org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.TokenFormat.OPAQUE; @JsonIgnoreProperties(ignoreUnknown = true) public class TokenPolicy { @@ -43,7 +43,7 @@ public class TokenPolicy { private boolean jwtRevocable = false; private boolean refreshTokenUnique = false; private boolean refreshTokenRotate = false; - private String refreshTokenFormat = JWT.getStringValue(); + private String refreshTokenFormat = OPAQUE.getStringValue(); @JsonGetter("keys") @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/model/src/test/java/org/cloudfoundry/identity/uaa/zone/TokenPolicyTest.java b/model/src/test/java/org/cloudfoundry/identity/uaa/zone/TokenPolicyTest.java index 8be55269e55..7f6b81b7c32 100644 --- a/model/src/test/java/org/cloudfoundry/identity/uaa/zone/TokenPolicyTest.java +++ b/model/src/test/java/org/cloudfoundry/identity/uaa/zone/TokenPolicyTest.java @@ -45,7 +45,7 @@ public void test_default_values() { assertFalse(policy.isRefreshTokenUnique()); assertFalse(policy.isJwtRevocable()); assertFalse(policy.isRefreshTokenRotate()); - assertEquals(TokenConstants.TokenFormat.JWT.getStringValue(), policy.getRefreshTokenFormat()); + assertEquals(TokenConstants.TokenFormat.OPAQUE.getStringValue(), policy.getRefreshTokenFormat()); } @Test diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointDocs.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointDocs.java index a80f7e057dd..f58d568267f 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointDocs.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointDocs.java @@ -66,7 +66,7 @@ class IdentityZoneEndpointDocs extends EndpointDocs { private static final String KEYS_CERT_DESC = "PEM encoded X.509 to be used in x5c, e.g. [RFC7517](https://tools.ietf.org/html/rfc7517#section-4.7)"; private static final String ACCESS_TOKEN_VALIDITY_DESC = "Time in seconds between when a access token is issued and when it expires. Defaults to global `accessTokenValidity`"; private static final String REFRESH_TOKEN_VALIDITY_DESC = "Time in seconds between when a refresh token is issued and when it expires. Defaults to global `refreshTokenValidity`"; - private static final String REFRESH_TOKEN_FORMAT = "The format for the refresh token. Allowed values are `jwt`, `opaque`. Defaults to `jwt`."; + private static final String REFRESH_TOKEN_FORMAT = "The format for the refresh token. Allowed values are `jwt`, `opaque`. Defaults to `opaque`."; private static final String REFRESH_TOKEN_UNIQUE = "If true, uaa will only issue one refresh token per client_id/user_id combination. Defaults to `false`."; private static final String REFRESH_TOKEN_ROTATE = "If true, uaa will issue a new refresh token value in grant type refresh_token. Defaults to `false`."; private static final String JWT_REVOCABLE_DESC = "Set to true if JWT tokens should be stored in the token store, and thus made individually revocable. Opaque tokens are always stored and revocable."; From e00071d8957b5f1e25a5afeadeb52e3c51118af2 Mon Sep 17 00:00:00 2001 From: strehle Date: Wed, 26 Jul 2023 11:25:40 +0200 Subject: [PATCH 3/3] more default changes --- .../uaa/oauth/DeprecatedUaaTokenServicesTests.java | 2 ++ .../uaa/mock/token/RefreshTokenMockMvcTests.java | 11 +++++++++-- .../mock/zones/IdentityZoneEndpointsMockMvcTests.java | 3 +-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/DeprecatedUaaTokenServicesTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/DeprecatedUaaTokenServicesTests.java index eb5f0a2aec8..19a3a3151ed 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/DeprecatedUaaTokenServicesTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/DeprecatedUaaTokenServicesTests.java @@ -706,6 +706,7 @@ public void testCreateAccessTokenRefreshGrant() { @Test public void testCreateAccessTokenRefreshGrant_with_an_old_refresh_token_format_containing_scopes_claim() { //Given + IdentityZoneHolder.get().getConfig().getTokenPolicy().setRefreshTokenFormat(JWT.getStringValue()); OAuth2AccessToken accessToken = getOAuth2AccessToken(); String refreshTokenJwt = accessToken.getRefreshToken().getValue(); @@ -1879,6 +1880,7 @@ public void testWrongClientDoesNotLeakToken() { @Test public void createRefreshToken_JwtDoesNotContainScopeClaim() { + IdentityZoneHolder.get().getConfig().getTokenPolicy().setRefreshTokenFormat(JWT.getStringValue()); AuthorizationRequest authorizationRequest = new AuthorizationRequest(CLIENT_ID, tokenSupport.requestedAuthScopes); Map authzParameters = new HashMap<>(authorizationRequest.getRequestParameters()); authzParameters.put(GRANT_TYPE, GRANT_TYPE_PASSWORD); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/RefreshTokenMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/RefreshTokenMockMvcTests.java index 4ec86b2b31c..0d7ef824107 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/RefreshTokenMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/RefreshTokenMockMvcTests.java @@ -139,6 +139,10 @@ void reset() { } private void createClientAndUserInRandomZone() throws Exception { + createClientAndUserInRandomZone(null); + } + + private void createClientAndUserInRandomZone(String refreshTokenFormat) throws Exception { RandomValueStringGenerator generator = new RandomValueStringGenerator(); zone = setupIdentityZone(generator.generate()); IdentityZoneHolder.set(zone); @@ -151,6 +155,9 @@ private void createClientAndUserInRandomZone() throws Exception { keys.put("key2", signingKey2); zone.getConfig().getTokenPolicy().setKeys(keys); zone.getConfig().getTokenPolicy().setActiveKeyId("key1"); + if (refreshTokenFormat != null) { + zone.getConfig().getTokenPolicy().setRefreshTokenFormat(refreshTokenFormat); + } zone = identityZoneProvisioning.update(zone); String clientId = "refreshclient"; @@ -284,7 +291,7 @@ void test_refresh_token_after_key_rotation() throws Exception { @Test void test_default_refresh_tokens_count() throws Exception { - createClientAndUserInRandomZone(); + createClientAndUserInRandomZone("jwt"); template.update("delete from revocable_tokens"); assertEquals(0, countTokens(client.getClientId(), user.getId())); getJwtRefreshToken(client.getClientId(), SECRET, user.getUserName(), SECRET, getZoneHostUrl(zone)); @@ -411,7 +418,7 @@ void refreshTokenGrantType_returnsIdToken_toOpenIdClients_withOpaqueRefreshToken @Test void refreshTokenGrantType_withJwtTokens_preservesRefreshTokenExpiryClaim() throws Exception { - createClientAndUserInRandomZone(); + createClientAndUserInRandomZone("jwt"); when(timeService.getCurrentTimeMillis()).thenReturn(1000L); CompositeToken tokenResponse = getTokensWithPasswordGrant(client.getClientId(), SECRET, user.getUserName(), SECRET, getZoneHostUrl(zone), "jwt"); String refreshToken = tokenResponse.getRefreshToken().getValue(); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java index 8faba7bdb49..6ef61f3a73e 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java @@ -63,7 +63,6 @@ import static org.cloudfoundry.identity.uaa.constants.OriginKeys.UAA; import static org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils.CookieCsrfPostProcessor.cookieCsrf; import static org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.GRANT_TYPE_AUTHORIZATION_CODE; -import static org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.TokenFormat.JWT; import static org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.TokenFormat.OPAQUE; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -2258,7 +2257,7 @@ private IdentityZone createZoneReturn() throws Exception { assertEquals(id.toLowerCase(), zone.getSubdomain()); assertFalse(zone.getConfig().getTokenPolicy().isRefreshTokenUnique()); assertFalse(zone.getConfig().getTokenPolicy().isRefreshTokenRotate()); - assertEquals(JWT.getStringValue(), zone.getConfig().getTokenPolicy().getRefreshTokenFormat()); + assertEquals(OPAQUE.getStringValue(), zone.getConfig().getTokenPolicy().getRefreshTokenFormat()); checkAuditEventListener(1, AuditEventType.IdentityZoneCreatedEvent, zoneModifiedEventListener, IdentityZone.getUaaZoneId(), "http://localhost:8080/uaa/oauth/token", "identity"); //validate that default groups got created