7

Spring Security OAuth2 を使用しています。クライアント アプリケーション (私たちが所有) は、ユーザーのユーザー名とパスワードを渡す "パスワード" 許可要求を作成します。ドラフトが指定するのと同じように。

カード番号、PIN、さらには許可を必要としない事前認証済みのパスワードなど、他の種類の資格情報もサポートするには、このメカニズムが必要です。

これらのリクエストは、私たちが所有するアプリケーションからのみ使用される特権 client_id によってのみ許可されることに注意してください。

4

2 に答える 2

7

デイブ、迅速な対応に感謝します。私は実際にあなたが参加した完璧な解決策を見つけました。それは「カスタム許可」トークン付与者と関係があります... https://jira.spring.io/browse/SECOAUTH-347

かなり古いバージョンの 1.0.0.M5 を更新していたら、それらについて知っていたかもしれません。

私のアプローチはAbstractTokenGranter、カスタム許可タイプをサポートするクラスで拡張することでした (私はそれを「studentCard」と呼んでいます)。ここで認証リクエストが行われると、 と同じようResourceOwnerPasswordTokenGranterにパラメーター リストを調べますが、代わりにカスタムの「cardNumber」パラメーターを探します。次に、独自の ID ベースのバージョンをUsernamePasswordAuthenticationTokenAuthenticationProvider に渡します。AuthenticationProvider は、ID カードに基づいてユーザーを認証する方法を知っています。

これが私が思いついたカスタム トークン グランター クラスです。

public class StudentCardTokenGranter extends AbstractTokenGranter {
    private static final String         GRANT_TYPE = "studentCard";

    private final AuthenticationManager authenticationManager;

    public StudentCardTokenGranter(AuthenticationManager authenticationManager,
        AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService) {
    super(tokenServices, clientDetailsService, GRANT_TYPE);
    this.authenticationManager = authenticationManager;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) {

    Map<String, String> parameters = clientToken.getAuthorizationParameters();
    String cardNumber = parameters.get("cardNumber");

    Authentication userAuth = new StudentCardAuthenticationToken(cardNumber);
    try {
        userAuth = authenticationManager.authenticate(userAuth);
    } catch (BadCredentialsException e) {
        // If the username/password are wrong the spec says we should send 400/bad grant
        throw new InvalidGrantException(e.getMessage());
    }
    if (userAuth == null || !userAuth.isAuthenticated()) {
        throw new InvalidGrantException("Could not authenticate student: " + cardNumber);
    }

    return new OAuth2Authentication(clientToken, userAuth);
    }
}

そして私の認可サーバーの設定:

<!-- Issues tokens for both client and client/user authorization requests -->
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
    <oauth:refresh-token />
    <oauth:client-credentials />
    <oauth:password authentication-manager-ref="myUserManager" />
    <oauth:custom-grant token-granter-ref="studentCardGranter" />
</oauth:authorization-server>
<bean id="studentCardGranter" class="com.api.security.StudentCardTokenGranter">
    <constructor-arg name="authenticationManager" ref="myUserManager" />
    <constructor-arg name="tokenServices" ref="tokenServices" />
    <constructor-arg name="clientDetailsService" ref="clientDetails" />
</bean>
于 2014-03-28T17:25:28.340 に答える
3

この仕様では、クライアントと認証サーバー間で直接、パスワードを使用せずにユーザー トークンを直接交換することは明示的に許可されていません。ただし、パスワード付与を他の形式の認証に拡張することは非常に自然なことだと思います。それは、文字によるものではないにしても、仕様の精神に基づいているため、関係の両側を所有している場合、うまくいかないことはあまりありません. Spring OAuth は、こ​​のようにパスワード許可を拡張するものを明示的にサポートしていませんが、それを行うのは難しくありません (実際には /token エンドポイントのセキュリティに関するものです)。私が見た別のアプローチは、パスワード許可プロトコルに固執することですが、「パスワード」を、ユーザーがこれらの代替方法のいずれかで認証されたことを知ることによってのみクライアントが取得できるワンタイムトークンにすることです。

于 2014-03-25T17:02:39.463 に答える