2017-01-20 32 views
0

私たちのアプリケーションには2つの部分があります。SAML認証されたUIからのAJAX APIコールの認証

  • Jersey 2.0を使用して異なるRESTエンドポイントを公開するJava 8で書かれたバックエンド。
  • Reactおよび他のノードモジュールを使用して構築された単一ページアプリケーションであるUI。

Webインターフェイスは、OktaでサポートされているSAML 2.0認証をIDプロバイダとして使用します。バックエンドはHTTPセッションを作成し、JSESSIONIDをCookieに送信します。

これでUIはデータを表示するためにRESTエンドポイントを呼び出します。私たちはREST APIの認証レイヤーを追加する必要があります。私はここで別の質問をしました。Authenticating rest endpoints and the UI using Okta

ここで私の質問は、UIが実際に認証され、HTTPセッションが有効なので、これらのAPI呼び出しに対する認証手段としてUIから渡すことができるものです。したがって、別のOAuth 2.0トークンを作成してUIに渡す必要はありません。そのため、UIはそれをバックエンドに渡すことができます。 OAuth 2.0のフローは、RESTエンドポイントを使用する外部クライアントにとって意味があります。

アップデート1

これは、認証方式の両方を定義して、私のsecurityContext.xmlの抜粋です。

<!-- Authenticating REST APIs --> 
<security:http pattern="/rest/**" use-expressions="false"> 
    <security:intercept-url pattern="/nltools/**" access="IS_AUTHENTICATED_FULLY" /> 
    <security:custom-filter before="BASIC_AUTH_FILTER" ref="authValidationFilter" /> 
    <security:http-basic/> 
</security:http> 

<!-- SAML processing endpoints --> 
<security:http pattern="/saml/**" entry-point-ref="samlEntryPoint"> 
    <security:custom-filter before="FIRST" ref="metadataGeneratorFilter" /> 
    <security:custom-filter before="CSRF_FILTER" ref="samlFilter" /> 
    <security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter" /> 
</security:http> 

<!-- Secured pages with SAML as entry point --> 
<security:http entry-point-ref="samlEntryPoint" use-expressions="false"> 
    <security:csrf /> 
    <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> 
    <security:custom-filter before="FIRST" ref="metadataGeneratorFilter" /> 
</security:http> 

<security:authentication-manager alias="authenticationManager"> 
    <security:authentication-provider ref="httpBasicAuthenticationProvider" /> 
    <!-- Register authentication manager for SAML provider --> 
    <security:authentication-provider ref="samlAuthenticationProvider"/> 
    <!-- Register authentication manager for administration UI --> 
    <security:authentication-provider> 
     <security:user-service id="adminInterfaceService"> 
      <security:user name="admin" password="admin" authorities="ROLE_ADMIN"/> 
     </security:user-service> 
    </security:authentication-provider> 
</security:authentication-manager> 

私はどのように私はSecurityContextPersistenceFilterを実行できることを確認していません。私は無効化し、私の/rest/**パターンのフィルタの1つを追加する必要がありますか?

return Promise.resolve().then(() => { 
 
     return request.post('/rest/v1/projects') 
 
     .send(data) 
 
     .then((success) => { 
 
      console.log('success!', success); 
 
      var projectName = success.body.name; 
 
      var projectId = success.body.id; 
 
      
 
      self.props.dispatch(projectActions.addNewProject(
 
      projectId, 
 
      projectName 
 
     )); 
 
     
 
      self.props.dispatch(appActions.displayGoodRequestMessage(projectName + " Saved")); 
 
      self.props.dispatch(projectActions.fetchProject(projectId)); 
 
      self.props.router.push('/projects'); 
 

 
     }

今JSコードを全て送信するように選択することができます

アップデート2

ここでは、バックエンドへの呼び出しを行うJSコード(リアクト)でありますバックエンドがJSESSION IDクッキーを取得することができますが、JSはそれを実行せず、私はその正しいことをするとは思いません。

一方、ブラウザでhttps://mydomain/rest/v1/projectsを実行すると、ログインしている間は、フィルタが有効なHTTPセッションをチェックしているので、リクエストからセッションを取得できるため、結果が表示されます。 request.getSession(false)ですが、JSがAPIを呼び出すときはそうではありません。完全に別のユーザーエージェントになります。

Update 3の提案パー

@ウラジミール・シェーファーによって、私は特別な何かをすることなく、.withCredentials()としてクッキーを送信し、バックエンドでの認証に少しだけ上のJSコードを変更することができ

return Promise.resolve().then(() => { 
 
     return request.post('/rest/v1/projects') 
 
     .withCredentials() 
 
     .send(data) 
 
     .then((success) => { 
 
      console.log('success!', success); 
 
      var projectName = success.body.name; 
 
      var projectId = success.body.id; 
 
      
 
      self.props.dispatch(projectActions.addNewProject(
 
      projectId, 
 
      projectName 
 
     )); 
 
     
 
      self.props.dispatch(appActions.displayGoodRequestMessage(projectName + " Saved")); 
 
      self.props.dispatch(projectActions.fetchProject(projectId)); 
 
      self.props.router.push('/projects'); 
 

 
     }

答えて

2

限りREST APIは、フロントエンドが本物のために使用する同じアプリケーションの一部であるとしてSpring Securityを使用すると、JSESSIONIDにアクセスできるため、認証されたユーザーに関するすべての情報を含むSpring Securityのコンテキストにアクセスできます。したがって、追加の認証メカニズムは必要ありません。あなたのジャージーのコールを処理するときに、フィルタSecurityContextPersistenceFilterを実行する場合は、使用してセキュリティコンテキストにアクセスできるようになります

SecurityContextHolder.getContext().getAuthentication(); 

SecurityContextPersistenceFilterは、認証対象とに格納を取得するために、その構成されたリポジトリを使用していますSecurityContextHolder。デフォルトで使用するHttpContextRepositoryを見てください。セキュリティコンテキストが格納されているのは、SPRING_SECURITY_CONTEXTのHttpSessionであるため、直接取得することもできます。

もちろん、フロントエンドの場合と同じように、Spring Securityを使用してREST APIの認証と認可を強制することもできます。すべてが処理されます。

+0

securityContext.xmlの抜粋で質問を更新しました。私はあなたがSecurityContextPeristenceFilterを実行することをいつ理解したのか分かりません。 – user320599

+0

私はあなたの質問から、あなたがSpring SecurityであなたのRESTを認証していないと推測しました。でも、君は。あなたのREST呼び出しは既に認証を必要としています。フロントエンドはそのままJSESSIONIDを送信します。あなたのアプリケーションの外部にある第三者がREST APIにアクセスできるようにしたい場合を除き、何もする必要はありません(次にOAuth遊びに来る)。 –

+0

これまでのご意見ありがとうございます。私はまだREST APIを呼び出すJavascriptコードの抜粋で私の質問を更新しました。現時点では、OAUTH2に切り替えるときに、将来、RESTエンドポイントを外部に公開したいと考えています。 – user320599

関連する問題