Add impersonation sample for token exchange

Closes gh-1604
This commit is contained in:
Steve Riesenberg
2024-05-01 17:46:12 -05:00
parent 76322dcfde
commit 1cda1ca36d
6 changed files with 51 additions and 12 deletions

View File

@@ -41,6 +41,8 @@ public class TokenExchangeConfig {
private static final String ACTOR_TOKEN_CLIENT_REGISTRATION_ID = "messaging-client-client-credentials";
private static final String IMPERSONATION_CLIENT_REGISTRATION_ID = "messaging-client-token-exchange-with-impersonation";
@Bean
public OAuth2AuthorizedClientProvider tokenExchange(
ClientRegistrationRepository clientRegistrationRepository,
@@ -87,6 +89,11 @@ public class TokenExchangeConfig {
OAuth2AuthorizedClientManager authorizedClientManager, String clientRegistrationId) {
return (context) -> {
// Do not provide an actor token for impersonation use case
if (IMPERSONATION_CLIENT_REGISTRATION_ID.equals(context.getClientRegistration().getRegistrationId())) {
return null;
}
// @formatter:off
OAuth2AuthorizeRequest authorizeRequest =
OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistrationId)

View File

@@ -21,10 +21,8 @@ import java.util.List;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClient;
@@ -44,11 +42,21 @@ public class UserController {
.build();
}
@GetMapping("/user/messages")
public List<String> getMessages(@AuthenticationPrincipal Jwt jwt,
@RegisteredOAuth2AuthorizedClient("messaging-client-token-exchange")
@GetMapping(value = "/user/messages", params = "use_case=delegation")
public List<String> getMessagesWithDelegation(
@RegisteredOAuth2AuthorizedClient("messaging-client-token-exchange-with-delegation")
OAuth2AuthorizedClient authorizedClient) {
return getUserMessages(authorizedClient);
}
@GetMapping(value = "/user/messages", params = "use_case=impersonation")
public List<String> getMessagesWithImpersonation(
@RegisteredOAuth2AuthorizedClient("messaging-client-token-exchange-with-impersonation")
OAuth2AuthorizedClient authorizedClient) {
return getUserMessages(authorizedClient);
}
private List<String> getUserMessages(OAuth2AuthorizedClient authorizedClient) {
// @formatter:off
String[] messages = Objects.requireNonNull(
this.restClient.get()
@@ -60,7 +68,7 @@ public class UserController {
// @formatter:on
List<String> userMessages = new ArrayList<>(Arrays.asList(messages));
userMessages.add("%s has %d unread messages".formatted(jwt.getSubject(), messages.length));
userMessages.add("%s has %d unread messages".formatted(authorizedClient.getPrincipalName(), messages.length));
return userMessages;
}

View File

@@ -19,13 +19,20 @@ spring:
client-secret: secret
authorization-grant-type: client_credentials
client-name: messaging-client-client-credentials
messaging-client-token-exchange:
messaging-client-token-exchange-with-delegation:
provider: spring
client-id: token-client
client-secret: token
authorization-grant-type: urn:ietf:params:oauth:grant-type:token-exchange
scope: message.read,message.write
client-name: messaging-client-token-exchange-with-delegation
messaging-client-token-exchange-with-impersonation:
provider: spring
client-id: token-client
client-secret: token
authorization-grant-type: urn:ietf:params:oauth:grant-type:token-exchange
scope: message.read
client-name: messaging-client-token-exchange
client-name: messaging-client-token-exchange-with-impersonation
provider:
spring:
issuer-uri: http://localhost:9000