Spring SecruityのOAuth APIを使用して、外部公開APIからアクセストークンを取得しようとしています。
このcurlコマンドは機能します(その内容は、アクセストークンを取得するために必要なすべてです):
curl -X POST \
https://api.app.com/v1/oauth/token \
-H 'content-type: application/x-www-form-urlencoded' \
-d'grant_type=client_credentials&client_id=bcfrtew123&client_secret=Y67493012'
このcurlコマンドを実行した後、外部サービスからアクセストークンを取得できます。
Spring Securityを使用する場合OAuth API:
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
SpringMVCコントローラーのメソッドを次のように設定します。
@RequestMapping(value = "/getAccessToken", method = RequestMethod.POST, consumes="application/x-www-form-urlencoded")
public OAuth2AccessToken getAccessToken(@RequestParam(value="client_id", required=true) String clientId, @RequestParam(value="client_secret", required=true) String clientSecret) throws Exception {
String tokenUri = "https://api.app.com/v1/oauth/token";
ResourceOwnerPasswordResourceDetails resourceDetails = new ResourceOwnerPasswordResourceDetails();
resourceDetails.setAccessTokenUri(tokenUri);
resourceDetails.setClientId(clientId);
resourceDetails.setClientSecret(clientSecret);
resourceDetails.setGrantType("client_credentials");
resourceDetails.setScope(Arrays.asList("read", "write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
oauth2RestTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
OAuth2AccessToken token = oauth2RestTemplate.getAccessToken();
return token;
}
ローカルのTomcatインスタンスからgetAccessToken呼び出しを呼び出すと、次のようになります。
access_denied
error_description=Unable to obtain a new access token for resource 'null'.
The provider manager is not configured to support it.
質問:
(content-typeは "application/x-www-form-urlencoded"である必要があることに注意してください...)
Spring Security OAuth APIを使用して、有効なcurlコマンドを模倣するにはどうすればよいですか?
これは、RequestParametersで設定したデフォルト値ですか?
成功した場合、リクエストを行う前にアクセストークンが常にプリロードされるように設定するにはどうすればよいですか?
実際の理由は、"client_credentials"
アクセストークンリクエストにResourceOwnerPasswordResourceDetails
を使用しているためです。 ResourceOwnerPasswordResourceDetails
とClientCredentialsResourceDetails
を入れ替えることはできません。
ClientCredentialsResourceDetails
では、AccessTokenUri, ClientId, ClientSecret
とgrantType
を設定する必要があります。 ResourceOwnerPasswordResourceDetails
では、Username and Password
とAccessTokenUri, ClientId, ClientSecret
およびGrantType
を提供する必要があります。
(一部の認証サーバーはusername and password
なしでpassword
トークン要求を受け入れます。しかし、私はそれが間違っていると思います)
これは私が使用するものです:
_@Bean
public RestTemplate oAuthRestTemplate() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setId("1");
resourceDetails.setClientId(oAuth2ClientId);
resourceDetails.setClientSecret(oAuth2ClientSecret);
resourceDetails.setAccessTokenUri(accessTokenUri);
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
return restTemplate;
}
_
正しいヘッダーはフレームワークによって設定されますが、ユーザー名/パスワードはAuthorizationヘッダー(基本認証)としてbase64エンコードされます。これはclient_credentials付与のOAuth2仕様です。
APIが仕様をサポートしているかどうかを確認します。
_curl -X POST \
'https://api.app.com/v1/oauth/token' \
-i -u 'client:secret' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials'
_
ユーザー名とパスワードを認証ヘッダーではなくデータとして送信する必要がある場合は、resourceDetails.setAuthenticationScheme(AuthenticationScheme.form);
を追加できます。これにより、ユーザー名とパスワードがデータとして設定されます。
サーバーがその特定のURLに投稿したコンテンツタイプを認識しないため、これが発生する可能性があります。 CURLリクエストに、httpヘッダーを使用するカスタムコントローラーの「content-type:application/x-www-form-urlencoded」を含めてみてください。
また、resourceDetailsのユーザー名とパスワードを設定していません。 resourceDetails.setUserName( "user"); resourceDetails.setUserName( "password");
これらが機能しない場合は、application/x-www-form-urlencodedでエンコードされたリクエストを抽出し、RestTemplateを介して文字列として渡して、トークンを取得できます。
追加のサポートが必要な場合はお知らせください。
トークンとして文字列応答を返す以下のコードを試してください。