2017-08-10 10 views
1

React/ReduxフロントエンドでSpringアプリケーションを開発しています。 Keycloak認証サービスとの統合に成功しました。しかし、アクセス・トークンがタイムアウトした後、望ましくない動作が発生しました。私たちのrestMiddlewareは、この(簡体字)のようになります。Keycloak |非同期関数のupdateToken()を待つことはできません

function restMiddleware() { 
    return (next) => async (action) => { 
     try{ 

      await keycloak.updateToken(5); 

      res = await fetch(restCall.url, { 
       ...restCall.options, ...{ 
        credentials: 'same-origin', 
        headers: { 
         Authorization: 'Bearer ' + keycloak.token 
        } 
       } 
      }); 

     }catch(e){} 
    } 

問題は、トークンの有効期限が切れるとupdateToken()が実行された後、非同期機能が停止しないということであり、そして新しいアクセストークンが受信される前に、すぐに)(フェッチ呼び出します。これはもちろんフェッチ要求が成功するのを防ぎ、コード401で応答を引き起こします。updateToken()はPromiseを返します。なぜなら、確かに起きていることはありません。

updateToken().success(*function*)の機能がトークンのリフレッシュを成功させた後に実行され、その内部にfetch()を配置すると問題が解決することが確認されましたが、私たちのミドルウェアの構築のためにできません。私はこの回避策を開発しました:

function refreshToken(minValidity) { 

     return new Promise((resolve, reject) => { 

      keycloak.updateToken(minValidity).success(function() { 
       resolve() 
      }).error(function() { 
       reject() 
      }); 
     }); 
    } 

    function restMiddleware() { 
    return (next) => async (action) => { 
     try{ 
      await refreshToken(5); 

      res = await fetch(restCall.url, { 
       ...restCall.options, ...{ 
        credentials: 'same-origin', 
        headers: { 
         Authorization: 'Bearer ' + keycloak.token 
        } 
       } 
      }); 

     }catch(e){} 
    } 

それはうまくいきますが、それは優雅ではありません。

質問は、最初の解決策が機能しなかった理由は何ですか?なぜ私はupdateToken()を待つことができず、代わりにupdateToken()。success()を使用する必要がありますか?

これはバグである可能性がありますが、これがこの質問の主な目的であることを確認してください。

答えて

0

updateTokenメソッドのドキュメントには、約束を返すと書かれていますが、実際には「可」ではないため、awaitキーワードは有効なPromiseとはみなされません。これは私がそれを置く方法です。 :)

あなたのソリューションは私にとって優雅に思えますし、updateToken関数を呼び出した後でPromiseチェーンを正しく続けるためにも同じことをしました。

Keycloak JavaScriptのアダプタのマニュアル:https://keycloak.gitbooks.io/documentation/securing_apps/topics/oidc/javascript-adapter.html

+1

のようにそれを使用する私は、このメソッドが定義されているkeycloak.js、に見て、私はポイントを見ることができます。 updateToken()が返すのはPromise(ECMAScript仕様のように)ではありません。 "updateTokenメソッドは、プロビジョニングオブジェクトを返します。プロビジョニングオブジェクトは、プロビジョニングオブジェクトを返します。プロビジョニングオブジェクトを使用すると、トークンが正常にリフレッシュされました。たとえば、ユーザーにエラーが表示されていない場合はエラーが表示されます。 私の意見では、この説明を使用してはならないことは非常に混乱しています。 – BJanusz

1

はい、とkeycloak.jsがES6約束に互換性がありませ自家製の約束の実装を使用して、言いました。私のprojetcsでやっているのは、このような小さなヘルパー(TypeScript)です。

export const keycloakPromise = <TSuccess>(keycloakPromise: KeycloakPromise<TSuccess, any>) => new Promise<TSuccess>((resolve, reject) => 
    keycloakPromise 
     .success((result: TSuccess) => resolve(result)) 
     .error((e: any) => reject(e)) 
); 

keycloakPromise<KeycloakProfile>(keycloak.loadUserProfile()) 
    .then(userProfile => ...) 
    .catch(() => ...) 
関連する問題