示例#1
0
        internal async override Task PreRunAsync()
        {
            IAccount account = await GetAccountFromParamsOrLoginHintAsync(_silentParameters).ConfigureAwait(false);

            AuthenticationRequestParameters.Account = account;

            AuthenticationRequestParameters.Authority = AuthenticationRequestParameters.AuthorityOverride == null
                ? Authority.CreateAuthorityWithTenant(ServiceBundle.Config.AuthorityInfo, account?.HomeAccountId?.TenantId)
                : Authority.CreateAuthorityWithOverride(
                AuthenticationRequestParameters.AuthorityOverride,
                ServiceBundle.Config.AuthorityInfo);
        }
        internal static void AuthorityDoesNotUpdateTenant(string authorityUri, string actualTenant)
        {
            Authority authority = AuthorityTestHelper.CreateAuthorityFromUrl(authorityUri);

            Assert.AreEqual(actualTenant, authority.GetTenantId());

            string updatedAuthority = authority.GetTenantedAuthority("other_tenant_id");

            Assert.AreEqual(actualTenant, authority.GetTenantId());
            Assert.AreEqual(updatedAuthority, authorityUri);

            authority = Authority.CreateAuthorityWithTenant(authority.AuthorityInfo, "other_tenant_id_2");

            Assert.AreEqual(authority.AuthorityInfo.CanonicalAuthority, authorityUri);
        }
示例#3
0
        public void TenantlessAuthorityChanges()
        {
            Authority authority = AuthorityTestHelper.CreateAuthorityFromUrl(
                TestConstants.AuthorityCommonTenant);

            Assert.AreEqual("common", authority.TenantId);

            string updatedAuthority = authority.GetTenantedAuthority(TestConstants.Utid);

            Assert.AreEqual(TestConstants.AuthorityUtidTenant, updatedAuthority);
            Assert.AreEqual(updatedAuthority, TestConstants.AuthorityUtidTenant);

            authority = Authority.CreateAuthorityWithTenant(
                authority.AuthorityInfo,
                TestConstants.Utid);

            Assert.AreEqual(authority.AuthorityInfo.CanonicalAuthority, TestConstants.AuthorityUtidTenant);
        }
        public void GlobalSetup()
        {
            var serviceBundle = TestCommon.CreateServiceBundleWithCustomHttpManager(null, isLegacyCacheEnabled: EnableLegacyCache);

            _requestContext = new RequestContext(serviceBundle, Guid.NewGuid());
            _cache          = new TokenCache(serviceBundle, false);
            _response       = TestConstants.CreateMsalTokenResponse();

            _requestParams = TestCommon.CreateAuthenticationRequestParameters(serviceBundle);
            _requestParams.TenantUpdatedCanonicalAuthority = Authority.CreateAuthorityWithTenant(
                _requestParams.AuthorityInfo,
                TestConstants.Utid);
            _requestParams.Account = new Account(TestConstants.s_userIdentifier, $"1{TestConstants.DisplayableId}", TestConstants.ProductionPrefNetworkEnvironment);

            AddHostToInstanceCache(serviceBundle, TestConstants.ProductionPrefCacheEnvironment);

            LegacyTokenCacheHelper.PopulateLegacyCache(serviceBundle.DefaultLogger, _cache.LegacyPersistence, TokenCacheSize);
            TokenCacheHelper.AddRefreshTokensToCache(_cache.Accessor, TokenCacheSize);
        }
        protected async Task <AuthenticationResult> CacheTokenResponseAndCreateAuthenticationResultAsync(MsalTokenResponse msalTokenResponse)
        {
            // developer passed in user object.
            AuthenticationRequestParameters.RequestContext.Logger.Info("Checking client info returned from the server..");

            ClientInfo fromServer = null;

            if (!AuthenticationRequestParameters.IsClientCredentialRequest &&
                AuthenticationRequestParameters.ApiId != ApiEvent.ApiIds.AcquireTokenByRefreshToken &&
                AuthenticationRequestParameters.AuthorityInfo.AuthorityType != AuthorityType.Adfs)
            {
                //client_info is not returned from client credential flows because there is no user present.
                fromServer = ClientInfo.CreateFromJson(msalTokenResponse.ClientInfo);
            }

            ValidateAccountIdentifiers(fromServer);

            IdToken idToken = IdToken.Parse(msalTokenResponse.IdToken);

            AuthenticationRequestParameters.TenantUpdatedCanonicalAuthority =
                Authority.CreateAuthorityWithTenant(AuthenticationRequestParameters.Authority.AuthorityInfo, idToken?.TenantId);


            AuthenticationRequestParameters.RequestContext.Logger.Info("Saving Token Response to cache..");

            var tuple = await CacheManager.SaveTokenResponseAsync(msalTokenResponse).ConfigureAwait(false);

            var atItem  = tuple.Item1;
            var idtItem = tuple.Item2;

            return(new AuthenticationResult(
                       atItem,
                       idtItem,
                       AuthenticationRequestParameters.AuthenticationScheme,
                       AuthenticationRequestParameters.RequestContext.CorrelationId,
                       msalTokenResponse.TokenSource));
        }
示例#6
0
        public async Task SaveMultipleAppmetadataAsync()
        {
            var serviceBundle         = TestCommon.CreateDefaultServiceBundle();
            ITokenCacheInternal cache = new TokenCache(serviceBundle);

            MsalTokenResponse response  = TestConstants.CreateMsalTokenResponse();
            MsalTokenResponse response2 = TestConstants.CreateMsalTokenResponse();

            response2.FamilyId = "1";

            var requestParams = CreateAuthenticationRequestParameters(serviceBundle);

            requestParams.TenantUpdatedCanonicalAuthority = Authority.CreateAuthorityWithTenant(
                requestParams.AuthorityInfo,
                TestConstants.Utid);
            AddHostToInstanceCache(serviceBundle, TestConstants.ProductionPrefNetworkEnvironment);

            await cache.SaveTokenResponseAsync(requestParams, response).ConfigureAwait(false);

            await cache.SaveTokenResponseAsync(requestParams, response2).ConfigureAwait(false);

            cache.Accessor.AssertItemCount(
                expectedAtCount: 1,
                expectedRtCount: 2, // a normal RT and an FRT
                expectedAccountCount: 1,
                expectedIdtCount: 1,
                expectedAppMetadataCount: 1);

            var metadata = cache.Accessor.GetAllAppMetadata().First();

            Assert.AreEqual(TestConstants.ClientId, metadata.ClientId);
            Assert.AreEqual(TestConstants.ProductionPrefNetworkEnvironment, metadata.Environment);
            Assert.AreEqual(TestConstants.FamilyId, metadata.FamilyId);

            Assert.IsTrue(cache.Accessor.GetAllRefreshTokens().Any(rt => rt.FamilyId == "1"));
            Assert.IsTrue(cache.Accessor.GetAllRefreshTokens().Any(rt => string.IsNullOrEmpty(rt.FamilyId)));
        }
示例#7
0
        async Task <Tuple <MsalAccessTokenCacheItem, MsalIdTokenCacheItem, Account> > ITokenCacheInternal.SaveTokenResponseAsync(
            AuthenticationRequestParameters requestParams,
            MsalTokenResponse response)
        {
            response.Log(requestParams.RequestContext.Logger, LogLevel.Verbose);

            MsalAccessTokenCacheItem  msalAccessTokenCacheItem  = null;
            MsalRefreshTokenCacheItem msalRefreshTokenCacheItem = null;
            MsalIdTokenCacheItem      msalIdTokenCacheItem      = null;
            MsalAccountCacheItem      msalAccountCacheItem      = null;

            IdToken idToken = IdToken.Parse(response.IdToken);

            if (idToken == null)
            {
                requestParams.RequestContext.Logger.Info("ID Token not present in response. ");
            }

            var tenantId = GetTenantId(idToken, requestParams);

            bool   isAdfsAuthority      = requestParams.AuthorityInfo.AuthorityType == AuthorityType.Adfs;
            string preferredUsername    = GetPreferredUsernameFromIdToken(isAdfsAuthority, idToken);
            string username             = isAdfsAuthority ? idToken?.Upn : preferredUsername;
            string homeAccountId        = GetHomeAccountId(requestParams, response, idToken);
            string suggestedWebCacheKey = SuggestedWebCacheKeyFactory.GetKeyFromResponse(requestParams, homeAccountId);

            // Do a full instance discovery when saving tokens (if not cached),
            // so that the PreferredNetwork environment is up to date.
            var instanceDiscoveryMetadata = await ServiceBundle.InstanceDiscoveryManager
                                            .GetMetadataEntryAsync(
                requestParams.Authority.AuthorityInfo,
                requestParams.RequestContext)
                                            .ConfigureAwait(false);

            #region Create Cache Objects
            if (!string.IsNullOrEmpty(response.AccessToken))
            {
                msalAccessTokenCacheItem =
                    new MsalAccessTokenCacheItem(
                        instanceDiscoveryMetadata.PreferredCache,
                        requestParams.AppConfig.ClientId,
                        response,
                        tenantId,
                        homeAccountId,
                        requestParams.AuthenticationScheme.KeyId)
                {
                    UserAssertionHash = requestParams.UserAssertion?.AssertionHash,
                    IsAdfs            = isAdfsAuthority
                };
            }

            if (!string.IsNullOrEmpty(response.RefreshToken))
            {
                msalRefreshTokenCacheItem = new MsalRefreshTokenCacheItem(
                    instanceDiscoveryMetadata.PreferredCache,
                    requestParams.AppConfig.ClientId,
                    response,
                    homeAccountId);

                if (!_featureFlags.IsFociEnabled)
                {
                    msalRefreshTokenCacheItem.FamilyId = null;
                }
            }

            Dictionary <string, string> wamAccountIds = GetWamAccountIds(requestParams, response);
            Account account;
            if (idToken != null)
            {
                msalIdTokenCacheItem = new MsalIdTokenCacheItem(
                    instanceDiscoveryMetadata.PreferredCache,
                    requestParams.AppConfig.ClientId,
                    response,
                    tenantId,
                    homeAccountId)
                {
                    IsAdfs = isAdfsAuthority
                };

                msalAccountCacheItem = new MsalAccountCacheItem(
                    instanceDiscoveryMetadata.PreferredCache,
                    response.ClientInfo,
                    homeAccountId,
                    idToken,
                    preferredUsername,
                    tenantId,
                    wamAccountIds);
            }

            #endregion

            account = new Account(
                homeAccountId,
                username,
                instanceDiscoveryMetadata.PreferredNetwork,
                wamAccountIds);
            requestParams.RequestContext.Logger.Verbose("[SaveTokenResponseAsync] Entering token cache semaphore. ");
            await _semaphoreSlim.WaitAsync().ConfigureAwait(false);

            requestParams.RequestContext.Logger.Verbose("[SaveTokenResponseAsync] Entered token cache semaphore. ");

            try
            {
#pragma warning disable CS0618 // Type or member is obsolete
                HasStateChanged = true;
#pragma warning restore CS0618 // Type or member is obsolete

                try
                {
                    ITokenCacheInternal tokenCacheInternal = this;
                    if (tokenCacheInternal.IsTokenCacheSerialized())
                    {
                        var args = new TokenCacheNotificationArgs(
                            this,
                            ClientId,
                            account,
                            hasStateChanged: true,
                            tokenCacheInternal.IsApplicationCache,
                            hasTokens: tokenCacheInternal.HasTokensNoLocks(),
                            requestParams.RequestContext.UserCancellationToken,
                            suggestedCacheKey: suggestedWebCacheKey);

                        Stopwatch sw = Stopwatch.StartNew();

                        await tokenCacheInternal.OnBeforeAccessAsync(args).ConfigureAwait(false);

                        await tokenCacheInternal.OnBeforeWriteAsync(args).ConfigureAwait(false);

                        requestParams.RequestContext.ApiEvent.DurationInCacheInMs += sw.ElapsedMilliseconds;
                    }

                    if (msalAccessTokenCacheItem != null)
                    {
                        requestParams.RequestContext.Logger.Info("Saving AT in cache and removing overlapping ATs...");

                        DeleteAccessTokensWithIntersectingScopes(
                            requestParams,
                            instanceDiscoveryMetadata.Aliases,
                            tenantId,
                            msalAccessTokenCacheItem.ScopeSet,
                            msalAccessTokenCacheItem.HomeAccountId,
                            msalAccessTokenCacheItem.TokenType);

                        _accessor.SaveAccessToken(msalAccessTokenCacheItem);
                    }

                    if (idToken != null)
                    {
                        requestParams.RequestContext.Logger.Info("Saving Id Token and Account in cache ...");
                        _accessor.SaveIdToken(msalIdTokenCacheItem);
                        MergeWamAccountIds(msalAccountCacheItem);
                        _accessor.SaveAccount(msalAccountCacheItem);
                    }

                    // if server returns the refresh token back, save it in the cache.
                    if (msalRefreshTokenCacheItem != null)
                    {
                        requestParams.RequestContext.Logger.Info("Saving RT in cache...");
                        _accessor.SaveRefreshToken(msalRefreshTokenCacheItem);
                    }

                    UpdateAppMetadata(requestParams.AppConfig.ClientId, instanceDiscoveryMetadata.PreferredCache, response.FamilyId);

                    // Do not save RT in ADAL cache for client credentials flow or B2C
                    if (ServiceBundle.Config.LegacyCacheCompatibilityEnabled &&
                        !requestParams.IsClientCredentialRequest &&
                        requestParams.AuthorityInfo.AuthorityType != AuthorityType.B2C)
                    {
                        var tenatedAuthority            = Authority.CreateAuthorityWithTenant(requestParams.AuthorityInfo, tenantId);
                        var authorityWithPreferredCache = Authority.CreateAuthorityWithEnvironment(
                            tenatedAuthority.AuthorityInfo,
                            instanceDiscoveryMetadata.PreferredCache);

                        CacheFallbackOperations.WriteAdalRefreshToken(
                            Logger,
                            LegacyCachePersistence,
                            msalRefreshTokenCacheItem,
                            msalIdTokenCacheItem,
                            authorityWithPreferredCache.AuthorityInfo.CanonicalAuthority,
                            msalIdTokenCacheItem.IdToken.ObjectId,
                            response.Scope);
                    }
                }
                finally
                {
                    ITokenCacheInternal tokenCacheInternal = this;
                    if (tokenCacheInternal.IsTokenCacheSerialized())
                    {
                        var args = new TokenCacheNotificationArgs(
                            this,
                            ClientId,
                            account,
                            hasStateChanged: true,
                            tokenCacheInternal.IsApplicationCache,
                            tokenCacheInternal.HasTokensNoLocks(),
                            requestParams.RequestContext.UserCancellationToken,
                            suggestedCacheKey: suggestedWebCacheKey);

                        Stopwatch sw = Stopwatch.StartNew();
                        await tokenCacheInternal.OnAfterAccessAsync(args).ConfigureAwait(false);

                        requestParams.RequestContext.ApiEvent.DurationInCacheInMs += sw.ElapsedMilliseconds;
                    }
#pragma warning disable CS0618 // Type or member is obsolete
                    HasStateChanged = false;
#pragma warning restore CS0618 // Type or member is obsolete
                }

                return(Tuple.Create(msalAccessTokenCacheItem, msalIdTokenCacheItem, account));
            }
            finally
            {
                _semaphoreSlim.Release();
                requestParams.RequestContext.Logger.Verbose("[SaveTokenResponseAsync] Released token cache semaphore. ");
            }
        }