diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/TokenProvider.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/TokenProvider.java index 2f3f95b7425..6b0dcea9731 100644 --- a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/TokenProvider.java +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/TokenProvider.java @@ -40,4 +40,12 @@ public interface TokenProvider { default void invalidate(ConnectionContext connectionContext) { } + /** + * Provides the name of the property in jwt which is effective for user identity (i.e. client_id for ClientCredentialsTokenProvider and user_name for PasswordGrantTokenProvider) + * + * @return + */ + default String getUserIdentityProperty(){ + return "user_name"; + } } diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_ClientCredentialsGrantTokenProvider.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_ClientCredentialsGrantTokenProvider.java index 2a665fbcb66..43480e48f41 100644 --- a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_ClientCredentialsGrantTokenProvider.java +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_ClientCredentialsGrantTokenProvider.java @@ -40,4 +40,8 @@ Mono tokenRequestTransformer(Mono outbound) { .then()); } + @Override + String getIdentityZoneSubdomain() { + return "client_id"; + } } diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_OneTimePasscodeTokenProvider.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_OneTimePasscodeTokenProvider.java index a1a8b029d6f..53d4ea67b41 100644 --- a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_OneTimePasscodeTokenProvider.java +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_OneTimePasscodeTokenProvider.java @@ -45,4 +45,8 @@ Mono tokenRequestTransformer(Mono outbound) { .then()); } + @Override + String getIdentityZoneSubdomain() { + return "client_id"; + } } diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_PasswordGrantTokenProvider.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_PasswordGrantTokenProvider.java index cb3cebc5d9b..8d96ea08005 100644 --- a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_PasswordGrantTokenProvider.java +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_PasswordGrantTokenProvider.java @@ -59,4 +59,8 @@ Mono tokenRequestTransformer(Mono outbound) { .then()); } + @Override + String getIdentityZoneSubdomain() { + return "user_name"; + } } diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_RefreshTokenGrantTokenProvider.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_RefreshTokenGrantTokenProvider.java index ff1fceb8268..dc5503e46a3 100644 --- a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_RefreshTokenGrantTokenProvider.java +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/tokenprovider/_RefreshTokenGrantTokenProvider.java @@ -45,4 +45,8 @@ Mono tokenRequestTransformer(Mono outbound) { .then()); } + @Override + String getIdentityZoneSubdomain() { + return "client_id"; + } } diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/uaa/UsernameProvider.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/uaa/UsernameProvider.java index 28a0fe5eff2..d2145faf390 100644 --- a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/uaa/UsernameProvider.java +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/uaa/UsernameProvider.java @@ -73,7 +73,7 @@ private String getUsername(String token) { .parseClaimsJws(token); return Optional - .ofNullable(jws.getBody().get("user_name", String.class)) + .ofNullable(jws.getBody().get(this.tokenProvider.getUserIdentityProperty(), String.class)) .orElseThrow(() -> new IllegalStateException("Unable to retrieve username from token")); } diff --git a/cloudfoundry-client-reactor/src/test/java/org/cloudfoundry/reactor/uaa/UsernameProviderTest.java b/cloudfoundry-client-reactor/src/test/java/org/cloudfoundry/reactor/uaa/UsernameProviderTest.java index a03d3e08ed3..3941f08589a 100644 --- a/cloudfoundry-client-reactor/src/test/java/org/cloudfoundry/reactor/uaa/UsernameProviderTest.java +++ b/cloudfoundry-client-reactor/src/test/java/org/cloudfoundry/reactor/uaa/UsernameProviderTest.java @@ -61,7 +61,8 @@ public void getInvalidToken() throws NoSuchAlgorithmException { String invalidToken = String.format("bearer %s", getToken(keyPair.getPrivate(), Instant.now().minus(Duration.ofHours(1)))); String validToken = String.format("bearer %s", getToken(keyPair.getPrivate(), Instant.now().plus(Duration.ofHours(1)))); when(this.tokenProvider.getToken(this.connectionContext)).thenReturn(Mono.just(invalidToken), Mono.just(validToken)); - + when(this.tokenProvider.getUserIdentityProperty()).thenReturn("user_name"); + this.usernameProvider .get() .as(StepVerifier::create) @@ -79,7 +80,8 @@ public void getValidToken() throws NoSuchAlgorithmException { String token = String.format("bearer %s", getToken(keyPair.getPrivate(), Instant.now().plus(Duration.ofHours(1)))); when(this.tokenProvider.getToken(this.connectionContext)).thenReturn(Mono.just(token)); - + when(this.tokenProvider.getUserIdentityProperty()).thenReturn("user_name"); + this.usernameProvider .get() .as(StepVerifier::create) @@ -87,6 +89,23 @@ public void getValidToken() throws NoSuchAlgorithmException { .expectComplete() .verify(Duration.ofSeconds(1)); } + + @Test + public void getValidTokenWithClient() throws NoSuchAlgorithmException { + KeyPair keyPair = getKeyPair(); + when(this.signingKeyResolver.resolveSigningKey(any(JwsHeader.class), any(Claims.class))).thenReturn(keyPair.getPublic()); + + String token = String.format("bearer %s", getToken(keyPair.getPrivate(), Instant.now().plus(Duration.ofHours(1)))); + when(this.tokenProvider.getToken(this.connectionContext)).thenReturn(Mono.just(token)); + when(this.tokenProvider.getUserIdentityProperty()).thenReturn("client_id"); + + this.usernameProvider + .get() + .as(StepVerifier::create) + .expectNext("test-client") + .expectComplete() + .verify(Duration.ofSeconds(1)); + } @SuppressWarnings("unchecked") private static String getToken(PrivateKey privateKey, Instant expiration) { @@ -94,6 +113,7 @@ private static String getToken(PrivateKey privateKey, Instant expiration) { .setHeader((Map) new DefaultJwsHeader().setKeyId("test-key")) .signWith(SignatureAlgorithm.RS256, privateKey) .claim("user_name", "test-username") + .claim("client_id", "test-client") .setExpiration(Date.from(expiration)) .compact(); }