Клиент Spring Security Oauth2 не может получить токен доступа с неверным кодом запроса = 415, сообщение = неподдерживаемJAVA

Программисты JAVA общаются здесь
Anonymous
Клиент Spring Security Oauth2 не может получить токен доступа с неверным кодом запроса = 415, сообщение = неподдерживаем

Сообщение Anonymous »

Используя Spring Boot, я настроил bean-компонент Oauth2RestTemplate в классе конфигурации и соответствующие свойства в файле свойств. Я использовал кодовый генератор Swagger для создания заглушки клиента. Когда я пытаюсь вызвать RESTful API, Spring не удается получить токен доступа, основной причиной которого является «неподдерживаемый тип носителя». Ниже приведена трассировка стека, моя конфигурация клиента Spring Security и мои попытки исправить. Будем очень признательны за любую помощь!
Получение токена из https://dev-api.some-domain.com/auth/oauth2/v1/token
ClientCredentialsAccessTokenProvider.doWithRequest — форма кодирования и отправки:
{grant_type=[client_credentials],scope=[read], client_id=[val from props], client_secret=[значение из реквизита]
error="access_denied", e r r o r _ d e s c r i p t i o n = " Т о к е н д о с т у п а з а п р е щ е н . < b r / > н а o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . t o k e n . O A u t h 2 A c c e s s T o k e n S u p p o r t . r e t r i e v e T o k e n ( O A u t h 2 A c c e s s T o k e n S u p p o r t . j a v a : 1 4 2 ) < b r / > н а o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . t o k e n . g r a n t . c l i e n t . C l i e n t C r e d e n t i a l s A c c e s s T o k e n P r o v i d e r . o b t a i n A c c e s s T o k e n ( C l i e n t C r e d e n t i a l s A c c e s s T o k e n P r o v i d e r . j a v a : 4 4 ) < b r / > н а o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . t o k e n . A c c e s s T o k e n P r o v i d e r C h a i n . o b t a i n N e w A c c e s s T o k e n I n t e r n a l ( A c c e s s T o k e n P r o v i d e r C h a i n . j a v a : 1 4 8 ) < b r / > н а o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . t o k e n . A c c e s s T o k e n P r o v i d e r C h a i n . o b t a i n A c c e s s T o k e n ( A c c e s s T o k e n P r o v i d e r C h a i n . j a v a : 1 2 1 ) < b r / > в o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . O A u t h 2 R e s t T e m p l a t e . a c q u i r e A c c e s s T o k e n ( O A u t h 2 R e s t T e m p l a t e . j a v a : 2 2 1 ) < b r / > в o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . O A u t h 2 R e s t T e m p l a t e . g e t A c c e s s T o k e n ( O A u t h 2 R e s t T e m p l a t e . j a v a : 1 7 3 ) < b r / > в o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . O A u t h 2 R e s t T e m p l a t e . c r e a t e R e q u e s t ( O A u t h 2 R e s t T e m p l a t e . j a v a : 1 0 5 ) < b r / > в o r g . s p r i n g f r a m e w o r k . w e b . c l i e n t . R e s t T e m p l a t e . d o E x e c u t e ( R e s t T e m p l a t e . j a v a : 7 3 5 ) < b r / > н а o r g . s p r i n g f r a m e w o r k . s e c u r i t y . o a u t h 2 . c l i e n t . O A u t h 2 R e s t T e m p l a t e . d o E x e c u t e ( O A u t h 2 R e s t T e m p l a t e . j a v a : 1 2 8 ) < b r / > н а o r g . s p r i n g f r a m e w o r k . w e b . c l i e n t . R e s t T e m p l a t e . e x c h a n g e ( R e s t T e m p l a t e . j a v a : 6 5 1 ) < b r / > н а c o m . m y . c o . s e r v i c e . h o l i d a y s . c l i e n t . i n v o k e r . A p i C l i e n t . i n v o k e A P I ( A p i C l i e n t . j a v a : 5 1 8 ) < b r / > н а c o m . m y . c o . s e r v i c e . h o l i d a y s . c l i e n t . a p i . H o l i d a y s A p i . g e t H o l i d a y s ( k H o l i d a y s A p i . j a v a : 1 8 3 ) < b r / > н а c o m . m y . c o . s e r v i c e . h o l i d a y . H o l i d a y s A p i T e s t . g e t H o l i d a y s T e s t ( H o l i d a y s A p i T e s t . j a v a : 6 6 ) < b r / > н а s u n . r e f l e c t . N a t i v e M e t h o d A c c e s s o r I m p l . i n v o k e 0 ( N a t i v e M e t h o d ) < b r / > a t s u n . r e f l e c t . N a t i v e M e t h o d A c c e s s o r I m p l . i n v o k e ( N a t i v e M e t h o d A c c e s s o r I m p l . j a v a : 6 2 ) < b r / > a t s u n . r e f l e c t . D e l e g a t i n g M e t h o d A c c e s s o r I m p l . i n v o k e ( D e l e g a t i n g M e t h o d A c c e s s o r I m p l . j a v a : 4 3 ) < b r / > н а j a v a . l a n g . r e f l e c t . M e t h o d . i n v o k e ( M e t h o d . j a v a : 4 9 8 ) < b r / > н а o r g . j u n i t . p l a t f o r m . c o m m o n s . u t i l . R e f l e c t i o n U t i l s . i n v o k e M e t h o d ( R e f l e c t i o n U t i l s . j a v a : 6 8 6 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . M e t h o d I n v o c a t e . p r o c e e d ( M e t h o d I n v o c a t e . j a v a : 6 0 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . I n v o c t i o n I n t e r c e p t o r C h a i n $ V a l i d a t i n g I n v o c a t e . p r o c e e d ( I n v o c t i o n I n t e r c e p t o r C h a i n . j a v a : 1 3 1 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x t e n s i o n . T i m e o u t E x t e n s i o n . i n t e r c e p t ( T i m e o u t E x t e n s i o n . j a v a : 1 4 9 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x t e n s i o n . T i m e o u t E x t e n s i o n . i n t e r c e p t T e s t a b l e M e t h o d ( T i m e o u t E x t e n s i o n . j a v a : 1 4 0 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x t e n s i o n . T i m e o u t E x t e n s i o n . i n t e r c e p t T e s t M e t h o d ( T i m e o u t E x t e n s i o n . j a v a : 8 4 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . E x e c u t a b l e I n v o k e r $ R e f l e c t i v e I n t e r c e p t o r C a l l . l a m b d a $ o f V o i d M e t h o d $ 0 ( E x e c u t a b l e I n v o k e r . j a v a : 1 1 5 ) < b r / > a t o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . E x e c u t a b l e I n v o k e r . l a m b d a $ i n v o k e $ 0 ( E x e c u t a b l e I n v o k e r . j a v a : 1 0 5 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . I n v o c a t e I n t e r c e p t o r C h a i n $ I n t e r c e p t e d I n v o k e . p r o c e e d ( I n v o k e I n t e r c e p t o r C h a i n . j a v a : 1 0 6 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . I n v o c t i o n I n t e r c e p t o r C h a i n . p r o c e e d ( I n v o c t i o n I n t e r c e p t o r C h a i n . j a v a : 6 4 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . I n v o c a t e I n t e r c e p t o r C h a i n . c h a i n A n d I n v o k e ( I n v o c t i o n I n t e r c e p t o r C h a i n . j a v a : 4 5 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . I n v o c t i o n I n t e r c e p t o r C h a i n . i n v o k e ( I n v o c t i o n I n t e r c e p t o r C h a i n . j a v a : 3 7 ) < b r / > н а o r g . j u n i t . j u p i t e r . e n g i n e . e x e c u t i o n . E x e c u t a b l e I n v o k e r . i n v o k e ( E x e c u t a b l e I n voker.java:104)
на org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
на org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
на org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
на org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
на org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
на org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$5(NodeTestTask.java:135)
на org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$7(NodeTestTask.java:125)
на org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$8(NodeTestTask.java:123)
на org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursically(NodeTestTask.java:122)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
на java.util.ArrayList.forEach(ArrayList.java:1257)
на org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$5(NodeTestTask.java:139)
на org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$7(NodeTestTask.java:125)
на org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$8(NodeTestTask.java:123)
на org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursically(NodeTestTask.java:122)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
на java.util.ArrayList.forEach(ArrayList.java:1257)
на org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$5(NodeTestTask.java:139)
на org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$7(NodeTestTask.java:125)
на org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursily$8(NodeTestTask.java:123)
на org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursically(NodeTestTask.java:122)
на org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
на org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
на org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
в org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
в org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
в org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
на org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
на org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
на org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
на com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
на com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
на com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
на com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
**Вызвано: error="invalid_request", error_description="{code=415, message=Unsupported Media Type}"**
в org.springframework.security.oauth2.common.Exceptions.OAuth2ExceptionJackson2Deserializer.deserialize(OAuth2ExceptionJackson2Deserializer.java:119)
в org.springframework.security.oauth2.common.Exceptions.OAuth2ExceptionJackson2Deserializer.deserialize(OAuth2ExceptionJackson2Deserializer.java:33)
на com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4524)
на com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3519)
на org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:269)
на org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readInternal(AbstractJackson2HttpMessageConverter.java:249)
на org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:199)
на org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport$AccessTokenErrorHandler.handleError(OAuth2AccessTokenSupport.java:237)
на org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
на org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:782)
на org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:740)
на org.springframework.web.client.RestTemplate.execute(RestTemplate.java:695)
на org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:137)
... еще 75

Ниже приведена моя конфигурация для клиента Oauth2
application.properties:
spring.security.oauth2.holiday.client.clientId=valid_key_is_here
spring.security.oauth2.holiday.client.clientSecret=valid_secret_is_here
spring.security.oauth2.holiday.client.accessTokenUri=https://dev-api.some-domain.com/auth/oauth2/v1/token
spring.security.oauth2.holiday.client.clientAuthenticationScheme=form
spring.security.oauth2.holiday.client.grantType=client_credentials
spring.security.oauth2.holiday.client.scope=read

@Configuration
@EnableOAuth2Client
public class SpringOauthRestClientConfig {

@Bean
@ConfigurationProperties("spring.security.oauth2.holiday.client")
public OAuth2ProtectedResourceDetails oAuthDetails() {
return new ClientCredentialsResourceDetails();
}

@Bean
public RestTemplate restTemplate() {
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oAuthDetails());

for (HttpMessageConverter converter : restTemplate.getMessageConverters()) {
if (converter instanceof AbstractJackson2HttpMessageConverter) {
ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter) converter).getObjectMapper();
mapper.registerModule(new JavaTimeModule());
}
}
// This allows us to read the response more than once - Necessary for debugging.
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory()));
return restTemplate;
}
}

Я попытался расширить класс Spring ClientCredentialsAccessTokenProvider, чтобы предоставить собственную реализацию метода getAccessToken(), чтобы я мог установить Content-Type в заголовке. Затем я добавляю свой собственный класс в RestTemplate. По-прежнему возникает та же ошибка, когда Spring пытается получить токен доступа.
public class ClientCredentialsCustomAccessTokenProvider extends ClientCredentialsAccessTokenProvider {

@Override
public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails details, AccessTokenRequest request) throws UserRedirectRequiredException, AccessDeniedException, OAuth2AccessDeniedException {
ClientCredentialsResourceDetails resource = (ClientCredentialsResourceDetails)details;

HttpHeaders headers1 = new HttpHeaders();
headers1.add("Content-Type", "application/x-www-form-urlencoded");

return retrieveToken(request, resource, this.getParametersForTokenRequest(resource), headers1);
}

Если я использую Postman для доступа к серверу авторизации, я успешно получаю обратно токен
{
"tokenType": "BearerToken",
"expiresIn": "899",
"accessToken": "dv6fnhBALtNzlhjMyCRfa9JDYodd"
}

используя эти настройки в Postman
POST request,
Authorization - Basic with my client_id/secret as username/password,
Headers - Content-Type = application/x-www-form-urlencoded,
Body - grant_type = client_credentials

В тесте JUnit я могу установить значение токена (и обойти внедрение RestTemplate Spring), используя ответ Postman, и без проблем вызвать службу.
HolidaysApi api = new HolidaysApi();
OAuth oAuth2 = (OAuth) api.getApiClient().getAuthentication("OAuth2");
oAuth2.setAccessToken("dv6fnhBALtNzlhjMyCRfa9JDYodd");

Вернуться в «JAVA»