2017-01-10 10 views
2

私は同様のissueを見つけましたが、回答がないので少し質問を重複するつもりです。Spring OAuth2:SSOとカスタム認証サーバーの両方で認証およびリソースアクセスをサポートします

私はSpring OAuth2を使用して、個別のリソースとカスタム認証サーバを実装しています。 私はすでに&のJWTトークンの検証を発行して認証サーバーとのやり取りを設定しました。

今SSO機能を追加しようとしていますが、実際にはそれに固執しています。私は公式のスプリングexamplesと付属のガイドを研究しましたが、カスタムサーバー認証でSSOの部分を接続するのは非常に短い言い方です。そして実際には、外部プロバイダーリソース( 'ユーザー'情報)のみを使用してプロセスを表示します。

このSSOの認証手段とカスタム登録のすべてを持っているのが普通だと思います。私はそれが例えばstackoverflowでうまく動作することがわかります。

複数のSSOプロバイダとカスタム認証サーバーから発行された異なる種類のトークンをリソースサーバーで処理する方法については、 私はこれを行うためにauth chainを使うことができ、それを処理する方法を知るためにトークンフォーマットを区別することができます。 Spring OAuth2で可能ですか?あるいは、私はこの魔法を何とか手動で行う必要がありますか?

今のところ私はちょうど1つの「たぶん奇妙な」アイデアを持っています: 自分のリソースサーバーにこのSSOの内容をまったく関与させないこと。 Facebookの(たとえば)トークンの受信後 - ちょうど

EDITEDカスタム認証サーバ(途中でユーザーを関連付けるまたは作成)とAPI JWTトークンのためにそれを交換して、標準の基礎の上にリソースサーバと連携: を私はしました少なくとも何かを発見した。私は認可連鎖でフィルタを設定し、指定されたソーシャルトークンを私のカスタムJWT-sに 'post authenticate'として翻訳しました(結局のところ狂気のアイデアではありません)。しかし、それは主にSpringSocialで行われました。 それでは、質問は、どうしたらいいですか? カスタムサーバーの認証にパスワード許可を使用していると忘れました。クライアントは信頼できるアプリケーションに過ぎず、ブラウザクライアントについてはわからない(ネイティブモバイルオプションのみを考えている)。私がブラウザクライアントを持っていると決めたとしても、それがバックエンドにsencetive情報を格納するようにするつもりです

答えて

2

これは私が2つの異なるライブラリ(Spring Social & OAuth2)を使っています。私は自分の道を行くことにしましたし、ちょうど春のOAuth2でそれを行う:

  • は私が持っているリソースサーバ、認証サーバとクライアント(JavaのでバックアップされたとのOAuth2クライアントライブラリを使用していますが、それは、他のクライアントになることができます) - 私のリソースは、カスタム登録の場合には私自身の認証サーバ

  • によって与えられた自分のJWTの認証トークンでのみ消費することができます。クライアントは、認証サーバからリフレッシュトークンを使用してJWTトークンを()を取得し、それを送信しますresサーバ。 Resサーバーは公開鍵で検証し、SSOの場合はクライアントがFacebook(またはその他のソーシャルプラットフォームトークン)を取得し、カスタム認証サーバーとのカスタムJWTトークンを交換して、

  • を返します。私はカスタムSocialTokenGranter(現在のところ、Facebookのソーシャルトークンのみを処理しています。すべてのソーシャルネットワークについては、別の許可タイプが必要です)を使用して認証サーバーに実装しました。このクラスは、トークンを検証してユーザー情報を取得するために、facebook認証サーバーを追加呼び出します。次に、dbからソーシャルユーザーを取得するか、またはnewを作成し、JWTトークンをクライアントに返します。これまでにユーザーマージは行われていません。今のところそれは範囲外です。

    public class SocialTokenGranter extends AbstractTokenGranter { 
    
    private static final String GRANT_TYPE = "facebook_social";  
    GiraffeUserDetailsService giraffeUserDetailsService; // custom UserDetails service 
    
    SocialTokenGranter(
         GiraffeUserDetailsService giraffeUserDetailsService, 
         AuthorizationServerTokenServices tokenServices, 
         OAuth2RequestFactory defaultOauth2RequestFactory, 
         ClientDetailsService clientDetailsService) { 
        super(tokenServices, clientDetailsService, defaultOauth2RequestFactory, GRANT_TYPE); 
        this.giraffeUserDetailsService = giraffeUserDetailsService; 
    } 
    
    @Override 
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails clientDetails, TokenRequest request) { 
    
        // retrieve social token sent by the client 
        Map<String, String> parameters = request.getRequestParameters(); 
        String socialToken = parameters.get("social_token"); 
    
        //validate social token and receive user information from external authentication server 
        String url = "https://graph.facebook.com/me?access_token=" + socialToken; 
    
        Authentication userAuth = null; 
        try {  
         ResponseEntity<FacebookUserInformation> response = new RestTemplate().getForEntity(url, FacebookUserInformation.class); 
    
         if (response.getStatusCode().is4xxClientError()) throw new GiraffeException.InvalidOrExpiredSocialToken(); 
    
         FacebookUserInformation userInformation = response.getBody(); 
         GiraffeUserDetails giraffeSocialUserDetails = giraffeUserDetailsService.loadOrCreateSocialUser(userInformation.getId(), userInformation.getEmail(), User.SocialProvider.FACEBOOK); 
    
         userAuth = new UsernamePasswordAuthenticationToken(giraffeSocialUserDetails, "N/A", giraffeSocialUserDetails.getAuthorities()); 
        } catch (GiraffeException.InvalidOrExpiredSocialToken | GiraffeException.UnableToValidateSocialUserInformation e) {    
         // log the stacktrace 
        } 
        return new OAuth2Authentication(request.createOAuth2Request(clientDetails), userAuth); 
    } 
    
    private static class FacebookUserInformation { 
        private String id; 
        private String email; 
    
        // getters, setters, constructor 
    }  
    

    }

そしてAuthorizationServerConfigurerAdapterを拡張するクラスから:

private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) { 
     List<TokenGranter> granters = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter())); 
     granters.add(new SocialTokenGranter(giraffeUserDetailsService, endpoints.getTokenServices(), endpoints.getOAuth2RequestFactory(), endpoints.getClientDetailsService())); 
     return new CompositeTokenGranter(granters); 
    } 

@Override 
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
    oauthServer 
      ... 
      .allowFormAuthenticationForClients() // to allow sending parameters as form fields 
      ... 

} 
すべてのJWTトークン要求をしようとしている

: "に応じて、 'ホストポート+/OAuthのトーク​​ン/' URL サーバーはそのような要求を別々に処理します。現在、私はデフォルトは「パスワード」(デフォルト)、「refresh_token」と「facebook_social」(カスタム)助成金の種類

「パスワード」グラントは、クライアントは次のパラメータを送信する必要があります入力しています

  • をCLIENTID
  • clientSecret(クライアントの種類に依存。ない単一ページクライアント用)

  • ユーザ名

  • :次のパラメータを送信する必要があり、クライアントを入力し 'refresh_token' 助成金を

  • grantType

(明示的に現在のクライアントのための認証サーバー設定で設定されていない場合)パスワード

  • スコープ

    • クライアントID

    • clientSecret(クライアントの種類によって異なります。 'facebook_social' グラントのためではない)単一ページのクライアントのための

    • refresh_token

    • grantType

    クライアントは、次のパラメータを送信する必要があります入力します。

    • をCLIENTID
    • facebook_social_tokエン(カスタムフィールド)クライアントに基づいて

    • grantType

      は異なるものになりますこれらの要求を送信する方法を設計します。 私の場合は、SpringのOAuth2ライブラリを使ってソーシャルトークンを取得するテストJavaベースのクライアントでは、コントローラのリダイレクト(コントローラは、facebook devページ設定で定義されたURLを使用して呼び出されます)

      これは2段階で処理することができます。Facebookのソーシャルトークンを取得した後JavaScriptはトークンを交換するために認証サーバーとは別の明示的な呼び出しを行うことができます。

      現在のJavaクライアントの実装例を見ることができますが、私はあなたが生産にJavaクライアントを使用するつもりだということを疑う:https://spring.io/guides/tutorials/spring-boot-oauth2/

  • +0

    は私が私の理解を確認してみましょう。あなたはFBからあなたのサーバーにすでに得られたトークンを渡しました。あなたのサーバーは新しいJWTを発行しましたか?どうやってこれを呼びましたか? URLは何でしたか?あなたがそれを達成するために使ったライブラリ – zalis

    +0

    @zalis私は最後に少し物事を明確にしようとしました。それが助けてくれることを願って。しかし、あなたのプロジェクトの技術的な要件によってはまだまだ違うかもしれません – maret

    関連する問題