Beispiel #1
0
        internal ServiceBundle(
            ApplicationConfiguration config,
            bool shouldClearCaches = false)
        {
            Config = config;

            DefaultLogger = new MsalLogger(
                Guid.Empty,
                config.ClientName,
                config.ClientVersion,
                config.LogLevel,
                config.EnablePiiLogging,
                config.IsDefaultPlatformLoggingEnabled,
                config.LoggingCallback);

            PlatformProxy = config.PlatformProxy ?? PlatformProxyFactory.CreatePlatformProxy(DefaultLogger);
            HttpManager   = config.HttpManager ?? new HttpManager(config.HttpClientFactory);

            if (config.TelemetryConfig != null)
            {
                // This can return null if the device isn't sampled in.  There's no need for processing MATS events if we're not going to send them.
                Mats             = TelemetryClient.CreateMats(config, PlatformProxy, config.TelemetryConfig);
                TelemetryManager = Mats?.TelemetryManager ?? new TelemetryManager(config, PlatformProxy, config.TelemetryCallback);
            }
            else
            {
                TelemetryManager = new TelemetryManager(config, PlatformProxy, config.TelemetryCallback);
            }

            AadInstanceDiscovery               = new AadInstanceDiscovery(DefaultLogger, HttpManager, TelemetryManager, shouldClearCaches);
            WsTrustWebRequestManager           = new WsTrustWebRequestManager(HttpManager);
            AuthorityEndpointResolutionManager = new AuthorityEndpointResolutionManager(this, shouldClearCaches);
        }
        public void ExpiredTokenRefreshFlowTest()
        {
            using (var httpManager = new MockHttpManager())
            {
                var        serviceBundle        = ServiceBundle.CreateWithCustomHttpManager(httpManager);
                var        aadInstanceDiscovery = new AadInstanceDiscovery(httpManager, new TelemetryManager());
                Authority  authority            = Authority.CreateAuthority(serviceBundle, MsalTestConstants.AuthorityHomeTenant, false);
                TokenCache cache = new TokenCache()
                {
                    ClientId      = MsalTestConstants.ClientId,
                    ServiceBundle = serviceBundle
                };
                _tokenCacheHelper.PopulateCache(cache.TokenCacheAccessor);

                AuthenticationRequestParameters parameters = new AuthenticationRequestParameters()
                {
                    Authority      = authority,
                    ClientId       = MsalTestConstants.ClientId,
                    Scope          = MsalTestConstants.Scope,
                    TokenCache     = cache,
                    RequestContext = new RequestContext(null, new MsalLogger(Guid.Empty, null)),
                    Account        = new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null)
                };

                // set access tokens as expired
                foreach (var atCacheItemStr in cache.GetAllAccessTokenCacheItems(new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))))
                {
                    MsalAccessTokenCacheItem accessItem =
                        JsonHelper.DeserializeFromJson <MsalAccessTokenCacheItem>(atCacheItemStr);
                    accessItem.ExpiresOnUnixTimestamp =
                        ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString(CultureInfo.InvariantCulture);

                    cache.AddAccessTokenCacheItem(accessItem);
                }
                TestCommon.MockInstanceDiscoveryAndOpenIdRequest(httpManager);

                httpManager.AddMockHandler(new MockHttpMessageHandler()
                {
                    Method          = HttpMethod.Post,
                    ResponseMessage = MockHelpers.CreateSuccessTokenResponseMessage()
                });

                var crypto = PlatformProxyFactory.GetPlatformProxy().CryptographyManager;

                SilentRequest request = new SilentRequest(
                    serviceBundle,
                    parameters,
                    ApiEvent.ApiIds.None,
                    false);

                Task <AuthenticationResult> task   = request.RunAsync(CancellationToken.None);
                AuthenticationResult        result = task.Result;
                Assert.IsNotNull(result);
                Assert.AreEqual("some-access-token", result.AccessToken);
                Assert.AreEqual(MsalTestConstants.Scope.AsSingleString(), result.Scopes.AsSingleString());
            }
        }
        public void SilentRefreshFailedNoCacheItemFoundTest()
        {
            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle        = ServiceBundle.CreateWithCustomHttpManager(httpManager);
                var aadInstanceDiscovery = new AadInstanceDiscovery(httpManager, new TelemetryManager());
                var authority            = Authority.CreateAuthority(serviceBundle, MsalTestConstants.AuthorityHomeTenant, false);
                _cache = new TokenCache()
                {
                    ClientId      = MsalTestConstants.ClientId,
                    ServiceBundle = serviceBundle
                };

                httpManager.AddInstanceDiscoveryMockHandler();

                var parameters = new AuthenticationRequestParameters()
                {
                    Authority = authority,
                    ClientId  = MsalTestConstants.ClientId,
                    Scope     = ScopeHelper.CreateSortedSetFromEnumerable(
                        new[]
                    {
                        "some-scope1",
                        "some-scope2"
                    }),
                    TokenCache     = _cache,
                    Account        = new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null),
                    RequestContext = new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))
                };

                var crypto           = PlatformProxyFactory.GetPlatformProxy().CryptographyManager;
                var telemetryManager = new TelemetryManager();

                try
                {
                    var request = new SilentRequest(serviceBundle, parameters, ApiEvent.ApiIds.None, false);
                    Task <AuthenticationResult> task = request.RunAsync(CancellationToken.None);
                    var authenticationResult         = task.Result;
                    Assert.Fail("MsalUiRequiredException should be thrown here");
                }
                catch (AggregateException ae)
                {
                    var exc = ae.InnerException as MsalUiRequiredException;
                    Assert.IsNotNull(exc, "Actual exception type is " + ae.InnerException.GetType());
                    Assert.AreEqual(MsalUiRequiredException.NoTokensFoundError, exc.ErrorCode);
                }
            }
        }
        public void FailedValidationMissingFieldsTest()
        {
            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager);

                //add mock response for instance validation
                httpManager.AddMockHandler(
                    new MockHttpMessageHandler
                {
                    Method      = HttpMethod.Get,
                    Url         = "https://login.windows.net/common/discovery/instance",
                    QueryParams = new Dictionary <string, string>
                    {
                        { "api-version", "1.0" },
                        { "authorization_endpoint", "https://login.microsoft0nline.com/mytenant.com/oauth2/v2.0/authorize" },
                    },
                    ResponseMessage = MockHelpers.CreateSuccessResponseMessage("{}")
                });

                var       aadInstanceDiscovery = new AadInstanceDiscovery(httpManager, new TelemetryManager());
                Authority instance             = Authority.CreateAuthority(serviceBundle, "https://login.microsoft0nline.com/mytenant.com", true);
                Assert.IsNotNull(instance);
                Assert.AreEqual(instance.AuthorityType, AuthorityType.Aad);
                try
                {
                    Task.Run(
                        async() =>
                    {
                        await instance.ResolveEndpointsAsync(
                            null,
                            new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))).ConfigureAwait(false);
                    }).GetAwaiter().GetResult();
                    Assert.Fail("validation should have failed here");
                }
                catch (Exception exc)
                {
                    Assert.IsNotNull(exc);
                }
            }
        }
        public void FailedTenantDiscoveryMissingEndpointsTest()
        {
            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager);

                //add mock response for tenant endpoint discovery
                httpManager.AddMockHandler(
                    new MockHttpMessageHandler
                {
                    Method          = HttpMethod.Get,
                    Url             = "https://login.microsoftonline.in/mytenant.com/v2.0/.well-known/openid-configuration",
                    ResponseMessage =
                        MockHelpers.CreateSuccessResponseMessage(
                            File.ReadAllText(ResourceHelper.GetTestResourceRelativePath("OpenidConfiguration-MissingFields.json")))
                });

                var       aadInstanceDiscovery = new AadInstanceDiscovery(httpManager, new TelemetryManager());
                Authority instance             = Authority.CreateAuthority(serviceBundle, "https://login.microsoftonline.in/mytenant.com", false);
                Assert.IsNotNull(instance);
                Assert.AreEqual(instance.AuthorityType, AuthorityType.Aad);
                try
                {
                    Task.Run(
                        async() =>
                    {
                        await instance.ResolveEndpointsAsync(
                            null,
                            new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))).ConfigureAwait(false);
                    }).GetAwaiter().GetResult();
                    Assert.Fail("validation should have failed here");
                }
                catch (MsalClientException exc)
                {
                    Assert.AreEqual(CoreErrorCodes.TenantDiscoveryFailedError, exc.ErrorCode);
                }
            }
        }
        public void ConstructorTests()
        {
            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle        = ServiceBundle.CreateWithCustomHttpManager(httpManager);
                var aadInstanceDiscovery = new AadInstanceDiscovery(httpManager, new TelemetryManager());
                var authority            = Authority.CreateAuthority(serviceBundle, MsalTestConstants.AuthorityHomeTenant, false);
                var cache = new TokenCache()
                {
                    ClientId      = MsalTestConstants.ClientId,
                    ServiceBundle = serviceBundle
                };
                var parameters = new AuthenticationRequestParameters()
                {
                    Authority      = authority,
                    ClientId       = MsalTestConstants.ClientId,
                    Scope          = MsalTestConstants.Scope,
                    TokenCache     = cache,
                    Account        = new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null),
                    RequestContext = new RequestContext(null, new MsalLogger(Guid.NewGuid(), null))
                };

                var crypto           = PlatformProxyFactory.GetPlatformProxy().CryptographyManager;
                var telemetryManager = new TelemetryManager();

                var request = new SilentRequest(serviceBundle, parameters, ApiEvent.ApiIds.None, false);
                Assert.IsNotNull(request);

                parameters.Account = new Account(MsalTestConstants.UserIdentifier, MsalTestConstants.DisplayableId, null);

                request = new SilentRequest(serviceBundle, parameters, ApiEvent.ApiIds.None, false);
                Assert.IsNotNull(request);

                request = new SilentRequest(serviceBundle, parameters, ApiEvent.ApiIds.None, false);
                Assert.IsNotNull(request);
            }
        }
        public void VerifyAuthorizationPendingErrorDoesNotLogError()
        {
            // When calling DeviceCodeFlow, we poll for the authorization and if the user hasn't entered the code in yet
            // then we receive an error for authorization_pending.  This is thrown as an exception and logged as
            // errors.  This error is noisy and so it should be suppressed for this one case.
            // This test verifies that the error for authorization_pending is not logged as an error.

            var logCallbacks = new List <_LogData>();

            Logger.LogCallback = (level, message, pii) =>
            {
                if (level == LogLevel.Error)
                {
                    Assert.Fail(
                        "Received an error message {0} and the stack trace is {1}",
                        message,
                        new StackTrace(true));
                }

                logCallbacks.Add(
                    new _LogData
                {
                    Level   = level,
                    Message = message,
                    IsPii   = pii
                });
            };

            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager);
                try
                {
                    const int NumberOfAuthorizationPendingRequestsToInject = 2;
                    var       parameters = CreateAuthenticationParametersAndSetupMocks(
                        httpManager,
                        NumberOfAuthorizationPendingRequestsToInject,
                        out HashSet <string> expectedScopes);

                    var aadInstanceDiscovery = new AadInstanceDiscovery(httpManager, new TelemetryManager());
                    _cache.ServiceBundle = serviceBundle;

                    var request = new DeviceCodeRequest(
                        serviceBundle,
                        parameters,
                        ApiEvent.ApiIds.None,
                        result => Task.FromResult(0));

                    Task <AuthenticationResult> task = request.RunAsync(CancellationToken.None);
                    task.Wait();

                    // Ensure we got logs so the log callback is working.
                    Assert.IsTrue(logCallbacks.Count > 0, "There should be data in logCallbacks");

                    // Ensure we have authorization_pending data in the logs
                    List <_LogData> authPendingLogs =
                        logCallbacks.Where(x => x.Message.Contains(OAuth2Error.AuthorizationPending)).ToList();
                    Assert.AreEqual(2, authPendingLogs.Count, "authorization_pending logs should exist");

                    // Ensure the authorization_pending logs are Info level and not Error
                    Assert.AreEqual(
                        2,
                        authPendingLogs.Where(x => x.Level == LogLevel.Info).ToList().Count,
                        "authorization_pending logs should be INFO");

                    // Ensure we don't have Error level logs in this scenario.
                    string errorLogs = string.Join(
                        "--",
                        logCallbacks
                        .Where(x => x.Level == LogLevel.Error)
                        .Select(x => x.Message)
                        .ToArray());



                    Assert.IsFalse(
                        logCallbacks.Any(x => x.Level == LogLevel.Error),
                        "Error level logs should not exist but got: " + errorLogs);
                }
                finally
                {
                    Logger.LogCallback = null;
                }
            }
        }