OAuth2DeviceAccessTokenResponseClient.java 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * Copyright 2020-2025 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * https://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package sample.authorization;
  17. import org.springframework.http.HttpHeaders;
  18. import org.springframework.http.converter.FormHttpMessageConverter;
  19. import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
  20. import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
  21. import org.springframework.security.oauth2.client.registration.ClientRegistration;
  22. import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
  23. import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
  24. import org.springframework.security.oauth2.core.OAuth2Error;
  25. import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
  26. import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
  27. import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
  28. import org.springframework.util.LinkedMultiValueMap;
  29. import org.springframework.util.MultiValueMap;
  30. import org.springframework.web.client.RestClient;
  31. import org.springframework.web.client.RestClientException;
  32. /**
  33. * @author Steve Riesenberg
  34. * @since 1.1
  35. */
  36. public final class OAuth2DeviceAccessTokenResponseClient implements OAuth2AccessTokenResponseClient<OAuth2DeviceGrantRequest> {
  37. private RestClient restClient;
  38. public OAuth2DeviceAccessTokenResponseClient() {
  39. this.restClient = RestClient.builder()
  40. .messageConverters((messageConverters) -> {
  41. messageConverters.clear();
  42. messageConverters.add(new FormHttpMessageConverter());
  43. messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
  44. })
  45. .defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
  46. .build();
  47. }
  48. public void setRestClient(RestClient restClient) {
  49. this.restClient = restClient;
  50. }
  51. @Override
  52. public OAuth2AccessTokenResponse getTokenResponse(OAuth2DeviceGrantRequest deviceGrantRequest) {
  53. ClientRegistration clientRegistration = deviceGrantRequest.getClientRegistration();
  54. HttpHeaders headerParameters = new HttpHeaders();
  55. /*
  56. * This sample demonstrates the use of a public client that does not
  57. * store credentials or authenticate with the authorization server.
  58. *
  59. * See DeviceClientAuthenticationProvider in the authorization server
  60. * sample for an example customization that allows public clients.
  61. *
  62. * For a confidential client, change the client-authentication-method
  63. * to client_secret_basic and set the client-secret to send the
  64. * OAuth 2.0 Token Request with a clientId/clientSecret.
  65. */
  66. if (!clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) {
  67. headerParameters.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret());
  68. }
  69. MultiValueMap<String, Object> requestParameters = new LinkedMultiValueMap<>();
  70. requestParameters.add(OAuth2ParameterNames.GRANT_TYPE, deviceGrantRequest.getGrantType().getValue());
  71. requestParameters.add(OAuth2ParameterNames.CLIENT_ID, clientRegistration.getClientId());
  72. requestParameters.add(OAuth2ParameterNames.DEVICE_CODE, deviceGrantRequest.getDeviceCode());
  73. try {
  74. // @formatter:off
  75. return this.restClient.post()
  76. .uri(deviceGrantRequest.getClientRegistration().getProviderDetails().getTokenUri())
  77. .headers((headers) -> headers.putAll(headerParameters))
  78. .body(requestParameters)
  79. .retrieve()
  80. .body(OAuth2AccessTokenResponse.class);
  81. // @formatter:on
  82. } catch (RestClientException ex) {
  83. OAuth2Error oauth2Error = new OAuth2Error("invalid_token_response",
  84. "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: "
  85. + ex.getMessage(), null);
  86. throw new OAuth2AuthorizationException(oauth2Error, ex);
  87. }
  88. }
  89. }