仕様によると、認証コードの付与を使用したトークンのリクエストは、_client_id
_がリクエストに含まれている限り、認証する必要はありませんand _client_id
_はコードの生成に使用されたものと同じもの。ただし、Spring Security OAuth 2.0の実装では、クライアントにシークレットが割り当てられていない場合でも、_/oauth/token
_エンドポイントで基本認証が常に必要であるように見えます。
ClientDetails
インターフェースのisSecretRequired()
メソッドにより、シークレットなしでクライアントを許可するためのサポートがあるようです。シークレットのないクライアントを_/oauth/token
_ URLで認証できるようにするには、何をする必要がありますか?
4.1.3。アクセストークンリクエスト
クライアントは、を送信してトークンエンドポイントにリクエストを送信します
「application/x-www-form-urlencoded」を使用した次のパラメーター
HTTPでUTF-8の文字エンコードを使用した付録Bの形式
リクエストエンティティ-本体:grant_typeが必要です。値は「authorization_code」に設定する必要があります。
コードが必要です。認証サーバーから受信した認証コード。
セクション4.1.1で説明されているように、「redirect_uri」パラメータが承認リクエストに含まれていて、それらの値が同一である必要がある場合は、redirect_uriが必要です。
セクション3.2.1で説明されているように、クライアントが認証サーバーで認証されていない場合は、client_idが必要です。
クライアントタイプが機密であるか、クライアントにクライアント資格情報が発行された(または他の認証要件が割り当てられた)場合、
クライアントは、説明されているように承認サーバーで認証する必要があります
セクション3.2.1。
以下のコードサンプルに示すように、基本認証の代わりにフォームパラメータを使用してクライアントを認証するには、allowFormAuthenticationForClients()
メソッドを使用します。
_class AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
@Override
void configure(AuthorizationServerSecurityConfigurer security) {
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients()
}
}
_
allowFormAuthenticationForClients()
メソッドはClientCredentialsTokenEndpointFilter
の追加をトリガーし、フォームパラメーターによる認証を可能にします。
Springでは、空のシークレットを使用してOAuth2クライアントを定義できます。これらは、「パブリック」クライアント、または秘密を保持できないクライアントと見なすことができます。 Javascriptアプリ、モバイルアプリなどを考えてみてください。通常、クライアントシークレットをそこに保存する必要はありません。
ご指摘のとおり、OAuth2仕様によれば、トークンエンドポイントはこれらのパブリッククライアントにシークレットを要求しないことを選択できます。
したがって、Springでは、空のシークレットを使用してOAuth2クライアントを定義し、限定された一連の付与タイプ(authorization_codeおよびrefresh_token)用に構成するだけです。
Spring Security実装トークンURLは、その特定のOAuth2クライアントのクライアントシークレットなしでトークン交換を受け入れます。
この問題を解決するには、クラスのメソッドloadUserByUsername
を参照してください:org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService
:
if (clientSecret == null || clientSecret.trim().length() == 0) {
clientSecret = this.emptyPassword;
}
おそらくあなたの場合、emptyPassword
はパスワードエンコーダーによって空のエンコードされたパスワードで初期化されていません。不足しているパスワードエンコーダーをAuthorizationServerConfigurerAdapter
に設定します。
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.passwordEncoder(passwordEncoder);
}
当初、私は受け入れられた答えと同様の設定をしていました。これは間違いなくこれを機能させるための前提条件です。しかし、欠けているのは、パスワードを単にnullに設定することはできないということです。たとえば、次のように、空のパスワードに設定する必要があります。
String secret = PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("");
clientDetails.setClientSecret(secret);
これを行わない場合でも、401を取得できます。