如何通过客户端凭证流中的 OAuth2AuthorizedClientService 获取访问令牌?
How do I get the Access Token via the OAuth2AuthorizedClientService in the Client Credentials Flow?
我创建了一个具有 Spring 安全性的客户端。作为授权服务器,我使用 Keycloak。
现在我想获得对访问令牌的访问权限,使用参数注释 @RegisteredOAuth2AuthorizedClient(registrationId = "keycloak")
我可以访问令牌,但是当我通过 OAuth2AuthorizedClientService
时,我只返回 NULL,我不明白为什么。
这是我的实现:
application.properties:
spring.security.oauth2.client.registration.keycloak.client-id=test-client
spring.security.oauth2.client.registration.keycloak.client-secret=b466bd4e-8dec-4af2-b90a-ab3fc06009b6
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8081/auth/realms/master
SecurityConfiguration.class
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Override
public void configure(HttpSecurity http) throws Exception
{
http.oauth2Client();
}
}
休息控制器:
@RestController
@RequestMapping("client")
public class ExampleRestController
{
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;
@GetMapping("resource")
public void runSecure(@RegisteredOAuth2AuthorizedClient(registrationId = "keycloak") OAuth2AuthorizedClient client)
{
var serviceClient = authorizedClientService.loadAuthorizedClient("keycloak", "anonymousUser");
System.out.println(serviceClient.getAccessToken()); // NULL
System.out.println((client.getAccessToken())); // NOT NULL
}
}
希望得到帮助,谢谢:)
编辑:
这是我使用服务灵活访问访问令牌的解决方案:
application.properties:
spring.security.oauth2.client.registration.keycloak.client-id=test-client
spring.security.oauth2.client.registration.keycloak.client-secret=b466bd4e-8dec-4af2-b90a-ab3fc06009b6
spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8081/auth/realms/master/protocol/openid-connect/token
客户注册:
@Configuration
public class ClientRegistrationConfiguration
{
private static final String KEYCLOAK = "keycloak";
@Bean
public ClientRegistration clientRegistration(OAuth2ClientProperties properties)
{
return withRegistrationId(KEYCLOAK)
.tokenUri(properties.getProvider().get(KEYCLOAK).getTokenUri())
.clientId(properties.getRegistration().get(KEYCLOAK).getClientId())
.clientSecret(properties.getRegistration().get(KEYCLOAK).getClientSecret())
.authorizationGrantType(CLIENT_CREDENTIALS)
.build();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository(ClientRegistration clientRegistration)
{
return new InMemoryClientRegistrationRepository(clientRegistration);
}
@Bean
public OAuth2AuthorizedClientService oAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository)
{
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientServiceOAuth2AuthorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService)
{
var authorizedClientProvider = builder().clientCredentials().build();
var authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
}
我的自定义令牌服务:
@Service
public class DefaultTokenService implements TokenService
{
@Autowired
private AuthorizedClientServiceOAuth2AuthorizedClientManager clientManager;
@Override
public OAuth2AccessToken getOAuth2AccessToken()
{
return Objects.requireNonNull(clientManager.authorize(withClientRegistrationId("keycloak").principal("Keycloak").build())).getAccessToken();
}
}
您需要自动装配 OAuth2AuthorizedClientManager bean 并显式发送令牌请求:
authorizedClientManager.authorize(request)
见https://docs.spring.io/spring-security/reference/servlet/oauth2/client/authorization-grants.html
我创建了一个具有 Spring 安全性的客户端。作为授权服务器,我使用 Keycloak。
现在我想获得对访问令牌的访问权限,使用参数注释 @RegisteredOAuth2AuthorizedClient(registrationId = "keycloak")
我可以访问令牌,但是当我通过 OAuth2AuthorizedClientService
时,我只返回 NULL,我不明白为什么。
这是我的实现:
application.properties:
spring.security.oauth2.client.registration.keycloak.client-id=test-client
spring.security.oauth2.client.registration.keycloak.client-secret=b466bd4e-8dec-4af2-b90a-ab3fc06009b6
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8081/auth/realms/master
SecurityConfiguration.class
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Override
public void configure(HttpSecurity http) throws Exception
{
http.oauth2Client();
}
}
休息控制器:
@RestController
@RequestMapping("client")
public class ExampleRestController
{
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;
@GetMapping("resource")
public void runSecure(@RegisteredOAuth2AuthorizedClient(registrationId = "keycloak") OAuth2AuthorizedClient client)
{
var serviceClient = authorizedClientService.loadAuthorizedClient("keycloak", "anonymousUser");
System.out.println(serviceClient.getAccessToken()); // NULL
System.out.println((client.getAccessToken())); // NOT NULL
}
}
希望得到帮助,谢谢:)
编辑:
这是我使用服务灵活访问访问令牌的解决方案:
application.properties:
spring.security.oauth2.client.registration.keycloak.client-id=test-client
spring.security.oauth2.client.registration.keycloak.client-secret=b466bd4e-8dec-4af2-b90a-ab3fc06009b6
spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8081/auth/realms/master/protocol/openid-connect/token
客户注册:
@Configuration
public class ClientRegistrationConfiguration
{
private static final String KEYCLOAK = "keycloak";
@Bean
public ClientRegistration clientRegistration(OAuth2ClientProperties properties)
{
return withRegistrationId(KEYCLOAK)
.tokenUri(properties.getProvider().get(KEYCLOAK).getTokenUri())
.clientId(properties.getRegistration().get(KEYCLOAK).getClientId())
.clientSecret(properties.getRegistration().get(KEYCLOAK).getClientSecret())
.authorizationGrantType(CLIENT_CREDENTIALS)
.build();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository(ClientRegistration clientRegistration)
{
return new InMemoryClientRegistrationRepository(clientRegistration);
}
@Bean
public OAuth2AuthorizedClientService oAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository)
{
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientServiceOAuth2AuthorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService)
{
var authorizedClientProvider = builder().clientCredentials().build();
var authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
}
我的自定义令牌服务:
@Service
public class DefaultTokenService implements TokenService
{
@Autowired
private AuthorizedClientServiceOAuth2AuthorizedClientManager clientManager;
@Override
public OAuth2AccessToken getOAuth2AccessToken()
{
return Objects.requireNonNull(clientManager.authorize(withClientRegistrationId("keycloak").principal("Keycloak").build())).getAccessToken();
}
}
您需要自动装配 OAuth2AuthorizedClientManager bean 并显式发送令牌请求:
authorizedClientManager.authorize(request)
见https://docs.spring.io/spring-security/reference/servlet/oauth2/client/authorization-grants.html