2017-04-24 17 views
2

私はAngularで書かれたSPAを書いており、ベアラトークンで保護されているリソース(APIなど)とともにAzure ADトークンベースの認証を使用しています。これにより、SPAはAzureから更新トークンを取得し、私が知る限り永遠にログインし続けることができます。私はこれを行うに角度のためADAL JavaScriptライブラリを使用していますADAL JS SPAの強制ログアウト

https://github.com/AzureAD/azure-activedirectory-library-for-js

今すぐ所定の時間にユーザーセッションを制限する必要があり、15時間を言うことができます。

私は、ログイン時にCookieを保存する素敵な小さなサービスを書いていました。すべてのリクエストはCookieの日付をチェックし、最大セッション制限を超えています。ユーザーがアプリを継続的に使用している場合やブラウザを閉じている場合は正常に動作しますが、ブラウザを開いたままにしておくと、トークンはバックグラウンドで更新され、ログインしたままです。

私は今、サイレント・サインアウト・ソリューションを使用します。意味、セッションが終了すると、ユーザーにSecure Sign In Pageを余儀なくされるようにしたいと思います。

これは一般的なシナリオのようですが、ADALはiFrameをバックグラウンドで使用するため、これを達成する方法を理解できないようです。私はタイマー/インターバルを使用することを考えましたが、それは厄介なようです。

私は以下のコードサンプルでadalAuthenticationService.logout()を使用しています。セッションキャッシュのクリアを試みましたが、ADALは自動的にトークンを更新します。私はまた、認証されていないページにredirectUriの場所を設定しようとしましたが、それでも、ユーザーがアクションを取った場合にのみリダイレクトされます。ブラウザが単に開いたままの場合、トークンは単にリセットされます。

var maxTime = 15; // hours allowed in session 

    // event to fire check; maybe this can be different, and is my problem? 
    $rootScope.$on('$viewContentLoaded', function() { 
     $scope.checkLogoutCookie(); 
    }); 
    $scope.logout = function() { 
     adalAuthenticationService.logout(); 
    }; 
    function setCookie(c) {} // implementation details don't matter.... 
    function getCookie(c) {} // implementation details don't matter.... 
    $scope.checkLogoutCookie = function() { 
     var lastLogin = getCookie("lastLogin"); 
     var loginDate = new Date(); 
     if (lastLogin === "") { // is empty 
      setCookie("lastLogin", loginDate, 365); 
     } else { 
      var lastDate = new Date(lastLogin); 
      var hours = Math.abs(lastDate - loginDate)/36e5; 
      if (hours > maxTime) { 
       setCookie("lastLogin", "", 0); 
       $scope.logout(); 
      } 
     } 
    } 

答えて

3

私は、ログイン時にクッキーを保存する素敵な小さなサービス、それがクッキーに日付をチェックし、彼らは彼らの最大セッションの制限を超えた場合は、すべての要求を書きました。ユーザーがアプリを継続的に使用している場合やブラウザを閉じている場合は正常に動作しますが、ブラウザを開いたままにしておくと、トークンは単にバックグラウンドで更新され、ログインしたままになります。

説明に基づいて、 adal-angular.jsのHTTPリクエストインターセプタの後にコードチェックの日付が実行されたようです。

可能であれば、この機能をADALライブラリのインターセプタの前に実装する必要があります。

不可能な場合は、ビジネスロジックを に変更して、トークンを取得する前にアプリセッションが期限切れになっていないかどうかを確認できます。そのためには、JavaScriptのActive Directory認証ライブラリ(ADAL)のソースコードを変更する必要があります。

たとえば、HTTPリクエストインターセプタadal-angular.jsを使用して、アプリケーションがセッション中であるかどうかを確認するコードを挿入できます。ここにあなたの参考のためのインターセプタのコードは次のとおりです。

AdalModule.factory('ProtectedResourceInterceptor', ['adalAuthenticationService', '$q', '$rootScope', '$templateCache', function (authService, $q, $rootScope, $templateCache) { 

    return { 
     request: function (config) { 
      if (config) { 

       config.headers = config.headers || {}; 

       // if the request can be served via templateCache, no need to token 
       if ($templateCache.get(config.url)) return config; 

       var resource = authService.getResourceForEndpoint(config.url); 
       authService.verbose('Url: ' + config.url + ' maps to resource: ' + resource); 
       if (resource === null) { 
        return config; 
       } 
//add/modify the code here 
       var tokenStored = authService.getCachedToken(resource); 
       if (tokenStored) { 
        authService.info('Token is available for this url ' + config.url); 
        // check endpoint mapping if provided 
        config.headers.Authorization = 'Bearer ' + tokenStored; 
        return config; 
       } 
       else { 
        // Cancel request if login is starting 
        if (authService.loginInProgress()) { 
         if (authService.config.popUp) { 
          authService.info('Url: ' + config.url + ' will be loaded after login is successful'); 
          var delayedRequest = $q.defer(); 
          $rootScope.$on('adal:loginSuccess', function (event, token) { 
           if (token) { 
            authService.info('Login completed, sending request for ' + config.url); 
            config.headers.Authorization = 'Bearer ' + tokenStored; 
            delayedRequest.resolve(config); 
           } 
          }); 
          return delayedRequest.promise; 
         } 
         else { 
          authService.info('login is in progress.'); 
          config.data = 'login in progress, cancelling the request for ' + config.url; 
          return $q.reject(config); 
         } 
        } 
        else { 
         // delayed request to return after iframe completes 
         var delayedRequest = $q.defer(); 
         authService.acquireToken(resource).then(function (token) { 
          authService.verbose('Token is available'); 
          config.headers.Authorization = 'Bearer ' + token; 
          delayedRequest.resolve(config); 
         }, function (error) { 
          config.data = error; 
          delayedRequest.reject(config); 
         }); 

         return delayedRequest.promise; 
        } 
       } 
      } 
     }, 
     responseError: function (rejection) { 
      authService.info('Getting error in the response: ' + JSON.stringify(rejection)); 
      if (rejection) { 
       if (rejection.status === 401) { 
        var resource = authService.getResourceForEndpoint(rejection.config.url); 
        authService.clearCacheForResource(resource); 
        $rootScope.$broadcast('adal:notAuthorized', rejection, resource); 
       } 
       else { 
        $rootScope.$broadcast('adal:errorResponse', rejection); 
       } 
       return $q.reject(rejection); 
      } 
     } 
    }; 
}]); 
1

adalAuthenticationServiceの方法logOut()を見てください。問題は、logout()を間違って使用したことです。 logout()メソッドの大文字のoに注意してください。

+0

これは質問に対する答えを提供しません。十分な[評判](https://stackoverflow.com/help/whats-reputation)があれば、[投稿にコメントする]ことができます(https://stackoverflow.com/help/privileges/comment)。代わりに、[質問者からの明確化を必要としない回答を提供する](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-c​​an- i-do-代わりに)。 - [レビューの投稿](レビュー/低品質の投稿/ 17680085) –

+0

はい!メモをありがとう。私はルールに従って答えを変えました。 –

関連する問題