Add impersonation sample for token exchange
Closes gh-1604
This commit is contained in:
@@ -165,6 +165,7 @@ public class AuthorizationServerConfig {
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
|
||||
.authorizationGrantType(new AuthorizationGrantType("urn:ietf:params:oauth:grant-type:token-exchange"))
|
||||
.scope("message.read")
|
||||
.scope("message.write")
|
||||
.build();
|
||||
|
||||
RegisteredClient mtlsDemoClient = RegisteredClient.withId(UUID.randomUUID().toString())
|
||||
|
||||
@@ -134,12 +134,27 @@ public class AuthorizationController {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/authorize", params = "grant_type=token_exchange")
|
||||
public String tokenExchangeGrant(Model model) {
|
||||
@GetMapping(value = "/authorize", params = {"grant_type=token_exchange", "use_case=delegation"})
|
||||
public String tokenExchangeGrantUsingDelegation(Model model) {
|
||||
|
||||
String[] messages = this.defaultClientWebClient
|
||||
.get()
|
||||
.uri(this.userMessagesBaseUri)
|
||||
.uri(this.userMessagesBaseUri + "?use_case=delegation")
|
||||
.attributes(clientRegistrationId("user-client-authorization-code"))
|
||||
.retrieve()
|
||||
.bodyToMono(String[].class)
|
||||
.block();
|
||||
model.addAttribute("messages", messages);
|
||||
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/authorize", params = {"grant_type=token_exchange", "use_case=impersonation"})
|
||||
public String tokenExchangeGrantUsingImpersonation(Model model) {
|
||||
|
||||
String[] messages = this.defaultClientWebClient
|
||||
.get()
|
||||
.uri(this.userMessagesBaseUri + "?use_case=impersonation")
|
||||
.attributes(clientRegistrationId("user-client-authorization-code"))
|
||||
.retrieve()
|
||||
.bodyToMono(String[].class)
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
<li><a class="dropdown-item" href="/authorize?grant_type=client_credentials&client_auth=client_secret" th:href="@{/authorize?grant_type=client_credentials&client_auth=client_secret}">Client Credentials (client_secret_basic)</a></li>
|
||||
<li><a class="dropdown-item" href="/authorize?grant_type=client_credentials&client_auth=mtls" th:href="@{/authorize?grant_type=client_credentials&client_auth=mtls}">Client Credentials (tls_client_auth)</a></li>
|
||||
<li><a class="dropdown-item" href="/authorize?grant_type=client_credentials&client_auth=self_signed_mtls" th:href="@{/authorize?grant_type=client_credentials&client_auth=self_signed_mtls}">Client Credentials (self_signed_tls_client_auth)</a></li>
|
||||
<li><a class="dropdown-item" href="/authorize?grant_type=token_exchange" th:href="@{/authorize?grant_type=token_exchange}">Token Exchange</a></li>
|
||||
<li><a class="dropdown-item" href="/authorize?grant_type=token_exchange" th:href="@{/authorize?grant_type=token_exchange&use_case=delegation}">Token Exchange (delegation)</a></li>
|
||||
<li><a class="dropdown-item" href="/authorize?grant_type=token_exchange" th:href="@{/authorize?grant_type=token_exchange&use_case=impersonation}">Token Exchange (impersonation)</a></li>
|
||||
<li><a class="dropdown-item" href="/authorize?grant_type=device_code" th:href="@{/authorize?grant_type=device_code}">Device Code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user