2017-01-23 3 views
0

からADAL TokenCacheに格納されて読み取ることができません。ユーザー認証のためのAzure ADによって保護されており、Webアプリケーションは、VIA OAuth 2.0ベアラトークンでも保護されているBackend Rest API(ASP.NET Web API 5.2.3)を呼び出します。 Open-ID Connect OWINモジュールを使用してWebアプリケーションでOpen-ID Connectプロトコルを使用しています。グラフAPIアクセストークン</p> <p>を次のようにStackOverflowに掲載中の質問は私たちがしているマルチテナントのWebアプリケーション(ASP.NET MVC 5.2.2)を持っているWebAPIの

グラフAPIバージョン1.5を使用して、テナントのAzure ADディレクトリユーザーとグループをアプリケーションストアに追加する必要があります。Microsoft ADAL 2.0を使用してアクセストークンと更新トークンを取得し、ADALトークンキャッシュに格納しますRedis Cacheに拡張されています。

デザインは、SignInUserId、ObjectId、TenantIdを含むWeb APIにユーザーコンテキストを渡すように設計されています.WebアプリケーションIDとともにこのコンテキストを使用して、TokenCacheに既に格納されているアクセストークンを読み取ります(アクセストークンを更新するために期限が切れた場合)、このトークンを使用してテナントADデータを取得します。

  // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc) 
      ClientCredential clientcred = new ClientCredential(clientId, appKey); 
      // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's EF DB 
      AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.microsoftonline.com/{0}", tenantID), new CustomTokenCache(signedInUserID)); 
      AuthenticationResult result = await authContext.AcquireTokenSilentAsync(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId)); 
      return result.AccessToken; 

トークンがキャッシュからすぐにアクセスされた場合でも、FailedToRefreshAccessToken例外がスローされたトークンを読みました。

ご協力いただければ幸いです。

Design

Exception details

コードカスタムトークンキャッシュの

public class PerUserCache 
    { 
     public string userUniqueId { get; set; } 
     public byte[] cacheBits { get; set; } 
     public DateTime LastWrite { get; set; } 

    } 

    public class CustomTokenCache : TokenCache 
    { 

     string userID; 
     PerUserCache Cache; 
     ICache database = CacheFactory.GetCacheInstance(); 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="userID"></param> 
     public CustomTokenCache(string userID) 
     { 
      // associate the cache to the web api 
      this.userID = userID; 

      this.AfterAccess = AfterAccessNotification; 
      this.BeforeAccess = BeforeAccessNotification; 
      this.BeforeWrite = BeforeWriteNotification; 

      // look up the entry in the DB 

       Cache = database.Get<PerUserCache>(this.userID); 

      // place the entry in memory 
      this.Deserialize((Cache == null) ? null : Cache.cacheBits); 
     } 

     // clean up the DB 
     public override void Clear() 
     { 
      base.Clear(); 
     } 
    enter code here 
     // Notification raised before ADAL accesses the cache. 
     // This is your chance to update the in-memory copy from the DB, if the in-memory version is stale 
     void BeforeAccessNotification(TokenCacheNotificationArgs args) 
     { 
      if (Cache == null) 
      { 
       // first time access 
        Cache = database.Get<PerUserCache>(userID); 
      }`enter code here` 
      else 
      { // retrieve last write from the DB 
       var status = database.Get<PerUserCache>(userID).LastWrite; 
       // if the in-memory copy is older than the persistent copy 
       if (status > Cache.LastWrite) 
       //// read from from storage, update in-memory copy 
       { 
        Cache = database.Get<PerUserCache>(userID); 
       } 
      } 
      this.Deserialize((Cache == null) ? null : Cache.cacheBits); 
     } 
     // Notification raised after ADAL accessed the cache. 
     // If the HasStateChanged flag is set, ADAL changed the content of the cache 
     void AfterAccessNotification(TokenCacheNotificationArgs args) 
     { 
      // if state changed 
      if (this.HasStateChanged) 
      { 
       Cache = new PerUserCache 
       { 
        userUniqueId = userID, 
        cacheBits = this.Serialize(), 
        LastWrite = DateTime.Now 
       }; 
       //// update the DB and the lastwrite     
       database.Set<PerUserCache>(userID, Cache,null); 
       this.HasStateChanged = false; 
      } 
     } 
     void BeforeWriteNotification(TokenCacheNotificationArgs args) 
     { 
      // if you want to ensure that no concurrent write take place, use this notification to place a lock on the entry 
     } 
    } 

}

+0

'FailedToRefreshAccessToken'例外に関する詳細な例外メッセージが表示されますか?また、 'CustomTokenCache'クラスに関するコードを共有することも役に立ちます。 –

+0

こんにちは@Fei Xueさん、投稿を編集しました – madhu

答えて

0

CustomTokenCacheのコードに関する問題がないと思われます。通常、この問題は特定のユーザーのキャッシュを見つけることができなかったために発生しました。

BeforeAccessNotificationの方法にブレークポイントを設定し、Cacheオブジェクトがデシリアライズされたときにヌルでないことを確認して、この問題を確認できます。

また、Redisのキャッシュは、userObjectIDに基づいて直接チェックすることもできます。

さらに、Web Appがトークンを上記の図のキャッシュストアに格納していることを指摘しているので、トークンを取得する方法については、Webアプリケーションのコードを共有してもよろしいですか?

+0

こんにちは、私たちは、私たちが脱税されたキャッシュオブジェクトを得ることができるCustomTokenCacheクラスをチェックしました.Webアプリケーションからアクセスされたときにトークンを取得できました。 Web APi例外がスローされる – madhu

+0

同じユーザーオブジェクトIDに基づいてキャッシュからトークンを取得したことを確認してください。また、** Web API **プロジェクトでデシリアライズされたときに 'Cache'オブジェクトがnullでないことを保証するためにWeb APIをデバッグすることをお勧めします。 –

関連する問題