public void ConstructorInitCombinations()
        {
            //no policy, user properties
            TokenCacheKey key = new TokenCacheKey(TestConstants.DefaultAuthorityHomeTenant,
                TestConstants.DefaultScope, TestConstants.DefaultClientId,
                TestConstants.DefaultUniqueId, TestConstants.DefaultDisplayableId, TestConstants.DefaultHomeObjectId);
            this.ValidateTokenCacheKey(key, true);

            //with policy, user properties
            key = new TokenCacheKey(TestConstants.DefaultAuthorityHomeTenant,
                TestConstants.DefaultScope, TestConstants.DefaultClientId,
                TestConstants.DefaultUniqueId, TestConstants.DefaultDisplayableId, TestConstants.DefaultHomeObjectId,
                TestConstants.DefaultPolicy);
            this.ValidateTokenCacheKey(key, false);


            User user = new User();
            user.DisplayableId = TestConstants.DefaultDisplayableId;
            user.UniqueId = TestConstants.DefaultUniqueId;
            user.HomeObjectId = TestConstants.DefaultHomeObjectId;

            //no policy, user object
            key = new TokenCacheKey(TestConstants.DefaultAuthorityHomeTenant,
                TestConstants.DefaultScope, TestConstants.DefaultClientId, user);
            this.ValidateTokenCacheKey(key, true);

            //with policy, user object
            key = new TokenCacheKey(TestConstants.DefaultAuthorityHomeTenant,
                TestConstants.DefaultScope, TestConstants.DefaultClientId, user,
                TestConstants.DefaultPolicy);
            this.ValidateTokenCacheKey(key, false);

        }
 internal User(User other)
 {
     this.UniqueId = other.UniqueId;
     this.DisplayableId = other.DisplayableId;
     this.HomeObjectId = other.HomeObjectId;
     this.Name = other.Name;
     this.ClientId = other.ClientId;
     this.TokenCache = other.TokenCache;
 }
 public static async Task<AuthenticationResult> GetTokenSilentAsync(User user)
 {
     TokenBroker brkr = new TokenBroker();
     PublicClientApplication app =
         new PublicClientApplication("7c7a2f70-caef-45c8-9a6c-091633501de4");
     try
     {
         return await app.AcquireTokenSilentAsync(brkr.Sts.ValidScope);
     }
     catch (Exception ex)
     {
         string msg = ex.Message + "\n" + ex.StackTrace;
         Console.WriteLine(msg);
         return await app.AcquireTokenAsync(brkr.Sts.ValidScope, user.DisplayableId, UiOptions.ActAsCurrentUser, null);
     }
     
 }
 internal void UpdateTenantAndUser(string tenantId, string idToken, User otherUser)
 {
     this.TenantId = tenantId;
     this.IdToken = idToken;
     if (otherUser != null)
     {
         this.User = new User(otherUser);
     }
 }
        internal async Task<AuthenticationResult> AcquireTokenSilentCommonAsync(Authenticator authenticator, string[] scope, User user, IPlatformParameters parameters, string policy, bool forceRefresh)
        {
            if (parameters == null)
            {
                parameters = PlatformPlugin.DefaultPlatformParameters;
            }

            var handler = new SilentRequest(this.GetHandlerData(authenticator, scope, policy, this.UserTokenCache), user, parameters, forceRefresh);
            return await handler.RunAsync().ConfigureAwait(false);
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="scope"></param>
 /// <param name="user"></param>
 /// <param name="authority"></param>
 /// <param name="policy"></param>
 /// <param name="forceRefresh"></param>
 /// <returns></returns>
 public async Task<AuthenticationResult> AcquireTokenSilentAsync(string[] scope, User user,
     string authority, string policy, bool forceRefresh)
 {
     Authenticator authenticator = new Authenticator(authority, this.ValidateAuthority, this.CorrelationId);
     return await this.AcquireTokenSilentCommonAsync(authenticator, scope, user, this.PlatformParameters, policy, forceRefresh).ConfigureAwait(false);
 }
        private async Task<AuthenticationResult> AcquireTokenCommonAsync(Authenticator authenticator, string[] scope, string[] additionalScope, Uri redirectUri, User user, UiOptions uiOptions, string extraQueryParameters, string policy)
        {
            if (this.PlatformParameters == null)
            {
                this.PlatformParameters = PlatformPlugin.DefaultPlatformParameters;
            }

            var handler =
                new InteractiveRequest(
                    this.GetHandlerData(authenticator, scope, policy, this.UserTokenCache), additionalScope, redirectUri,
                    this.PlatformParameters, user, uiOptions, extraQueryParameters,
                    this.CreateWebAuthenticationDialog(this.PlatformParameters));
            return await handler.RunAsync().ConfigureAwait(false);
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="scope"></param>
 /// <param name="user"></param>
 /// <param name="options"></param>
 /// <param name="extraQueryParameters"></param>
 /// <param name="additionalScope"></param>
 /// <param name="authority"></param>
 /// <param name="policy"></param>
 /// <returns></returns>
 public async Task<AuthenticationResult> AcquireTokenAsync(string[] scope, User user,
     UiOptions options, string extraQueryParameters, string[] additionalScope, string authority, string policy)
 {
     Authenticator authenticator = new Authenticator(authority, this.ValidateAuthority, this.CorrelationId);
     return
         await
             this.AcquireTokenCommonAsync(authenticator, scope, additionalScope, new Uri(this.RedirectUri), user,
                 options, extraQueryParameters, policy).ConfigureAwait(false);
 }
 private List<KeyValuePair<TokenCacheKey, AuthenticationResultEx>> QueryCache(string authority, string clientId,
     User user, string policy)
 {
     return this.QueryCache(
         authority, clientId, user?.UniqueId, user?.DisplayableId, user?.HomeObjectId, policy);
 }
        internal KeyValuePair<TokenCacheKey, AuthenticationResultEx>? LoadSingleItemFromCache(string authority,
            HashSet<string> scope, string clientId, User user,
            string policy, CallState callState)
        {
            lock (lockObject)
            {
                string uniqueId = null;
                string displayableId = null;
                string rootId = null;

                if (user != null)
                {
                    uniqueId = user.UniqueId;
                    displayableId = user.DisplayableId;
                    rootId = user.HomeObjectId;
                }

                if (uniqueId == null && displayableId == null && rootId == null)
                {
                    PlatformPlugin.Logger.Information(null, "No user information provided.");
                    // if authority is common and there are multiple unique ids in the cache
                    // then throw MultipleTokensMatched because code cannot guess which user
                    // is requested by the developer.
                    if (Authenticator.IsTenantLess(authority) && this.GetUniqueIdsFromCache(clientId).Count() > 1)
                    {
                        throw new MsalException(MsalError.MultipleTokensMatched);
                    }
                }

                if (Authenticator.IsTenantLess(authority))
                {
                    authority = null; //ignore authority
                }

                // First identify all potential tokens.
                List<KeyValuePair<TokenCacheKey, AuthenticationResultEx>> items = this.QueryCache(authority, clientId,
                    uniqueId, displayableId, rootId, policy);

                //using ScopeContains because user could be accessing a subset of the scope.
                List<KeyValuePair<TokenCacheKey, AuthenticationResultEx>> scopeSpecificItems =
                    items.Where(p => p.Key.ScopeContains(scope)).ToList();

                int scopeValuesCount = scopeSpecificItems.Count();
                KeyValuePair<TokenCacheKey, AuthenticationResultEx>? returnValue = null;
                switch (scopeValuesCount)
                {
                    case 1:
                        PlatformPlugin.Logger.Information(callState,
                            "An item matching the requested scope set was found in the cache");
                        returnValue = scopeSpecificItems.First();
                        break;
                    case 0:
                    {
                        //look for intersecting scope first
                        scopeSpecificItems =
                            items.Where(p => p.Key.ScopeIntersects(scope)).ToList();
                        if (!scopeSpecificItems.Any())
                        {
                            //Choose any of the MRRT tokens if there are any.
                            scopeSpecificItems =
                                items.Where(p => p.Value.IsMultipleScopeRefreshToken).ToList();

                            if (scopeSpecificItems.Any())
                            {
                                returnValue = scopeSpecificItems.First();
                                PlatformPlugin.Logger.Information(callState,
                                    "A Multi Scope Refresh Token for a different scope was found which can be used");
                            }
                        }
                        else
                        {
                            returnValue = scopeSpecificItems.First(); //return intersecting scopes
                        }
                    }
                        break;
                    default:
                        throw new MsalException(MsalError.MultipleTokensMatched);
                }

                if (user != null)
                {
                    // check for tokens issued to same client_id/user_id combination, but any tenant.
                    // cross tenant should not be used when there is no user provided, unless we are running in 
                    // RestrictToSingleUser mode.
                    if (returnValue == null)
                    {
                        List<KeyValuePair<TokenCacheKey, AuthenticationResultEx>> itemsForAllTenants = this.QueryCache(
                            null, clientId, null, null, rootId, policy);
                        if (itemsForAllTenants.Count > 0)
                        {
                            returnValue = itemsForAllTenants.First();
                        }
                    }

                    // look for family of client id
                    if (returnValue == null)
                    {
                        // set authority and client id to null.
                        List<KeyValuePair<TokenCacheKey, AuthenticationResultEx>> itemsForFamily =
                            this.QueryCache(null, null, null, null, rootId, policy)
                                .Where(kvp => kvp.Value.Result != null && kvp.Value.Result.FamilyId != null).ToList();
                        if (itemsForFamily.Count > 0)
                        {
                            returnValue = itemsForFamily.First();
                        }
                    }
                }

                return returnValue;
            }
        }
        internal virtual AuthenticationResultEx LoadFromCache(string authority, HashSet<string> scope, string clientId, User user, string policy, CallState callState)
        {
            lock (lockObject)
            {
                PlatformPlugin.Logger.Verbose(callState, "Looking up cache for a token...");
                AuthenticationResultEx resultEx = null;

                //get either a matching token or an MRRT supported RT
                KeyValuePair<TokenCacheKey, AuthenticationResultEx>? kvp = this.LoadSingleItemFromCache(authority, scope,
                    clientId, user, policy, callState);
                TokenCacheKey cacheKey = null;
                if (kvp.HasValue)
                {
                    cacheKey = kvp.Value.Key;
                    resultEx = kvp.Value.Value;
                    bool tokenNearExpiry = (resultEx.Result.ExpiresOn <=
                                            DateTime.UtcNow + TimeSpan.FromMinutes(Constant.ExpirationMarginInMinutes));
                    if (!cacheKey.ScopeContains(scope) ||
                        (!Authenticator.IsTenantLess(authority) && !authority.Equals(cacheKey.Authority)) ||
                        !clientId.Equals(cacheKey.ClientId))
                    {
                        //requested scope are not a subset or authority does not match (cross-tenant RT) or client id is not same (FoCI).
                        PlatformPlugin.Logger.Verbose(callState,
                            string.Format(CultureInfo.InvariantCulture,"Refresh token for scope '{0}' will be used to acquire token for '{1}'",
                                cacheKey.Scope.AsSingleString(),
                                scope.AsSingleString()));

                        resultEx = CreateResultExFromCacheResultEx(cacheKey, resultEx);
                    }
                    else if (tokenNearExpiry)
                    {
                        resultEx.Result.Token = null;
                        PlatformPlugin.Logger.Verbose(callState,
                            "An expired or near expiry token was found in the cache");
                    }
                    else
                    {
                        PlatformPlugin.Logger.Verbose(callState,
                            string.Format(CultureInfo.InvariantCulture,"{0} minutes left until token in cache expires",
                                (resultEx.Result.ExpiresOn - DateTime.UtcNow).TotalMinutes));
                    }

                    // client credential tokens do not have associated refresh tokens.
                    if (resultEx.Result.Token == null && resultEx.RefreshToken == null)
                    {
                        this.tokenCacheDictionary.Remove(cacheKey);
                        PlatformPlugin.Logger.Information(callState, "An old item was removed from the cache");
                        this.HasStateChanged = true;
                        resultEx = null;
                    }

                    if (resultEx != null)
                    {
                        PlatformPlugin.Logger.Information(callState,
                            "A matching item (access token or refresh token or both) was found in the cache");
                    }
                }

                return resultEx;
            }
        }