Ejemplo n.º 1
0
        private async Task <AuthorizationResult> AcquireAuthCodeAsync(
            string redirectUri       = TestRedirectUri,
            string requestUri        = TestAuthorizationRequestUri,
            string responseUriString = TestAuthorizationResponseUri)
        {
            // Arrange
            var    requestContext = new RequestContext(TestCommon.CreateDefaultServiceBundle(), Guid.NewGuid());
            var    responseUri    = new Uri(responseUriString);
            IWebUI webUI          = new DefaultOsBrowserWebUi(_platformProxy, _logger, _tcpInterceptor);

            _tcpInterceptor.ListenToSingleRequestAndRespondAsync(
                TestPort,
                Arg.Any <Func <Uri, string> >(),
                CancellationToken.None)
            .Returns(Task.FromResult(responseUri));

            // Act
            AuthorizationResult authorizationResult = await webUI.AcquireAuthorizationAsync(
                new Uri(requestUri),
                new Uri(redirectUri),
                requestContext,
                CancellationToken.None).ConfigureAwait(false);

            // Assert that we opened the browser
            await _platformProxy.Received(1).StartDefaultOsBrowserAsync(requestUri)
            .ConfigureAwait(false);

            return(authorizationResult);
        }
Ejemplo n.º 2
0
        private static IPublicClientApplication CreatePca()
        {
            IPublicClientApplication pca = PublicClientApplicationBuilder
                                           .Create(s_clientIdForPublicApp)
                                           .WithAuthority(GetAuthority())
                                           .WithLogging(Log, LogLevel.Verbose, true)
                                           .WithRedirectUri(DefaultOsBrowserWebUi.FindFreeLocalhostRedirectUri()) // required for DefaultOsBrowser
                                           .Build();

            pca.UserTokenCache.SetBeforeAccess(notificationArgs =>
            {
                notificationArgs.TokenCache.DeserializeMsalV3(File.Exists(CacheFilePath)
                    ? File.ReadAllBytes(CacheFilePath)
                    : null);
            });
            pca.UserTokenCache.SetAfterAccess(notificationArgs =>
            {
                // if the access operation resulted in a cache update
                if (notificationArgs.HasStateChanged)
                {
                    // reflect changes in the persistent store
                    File.WriteAllBytes(CacheFilePath, notificationArgs.TokenCache.SerializeMsalV3());
                }
            });
            return(pca);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Apply this authenticator to the given authentication parameters.
        /// </summary>
        /// <param name="parameters">The complex object containing authentication specific information.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>
        /// An instance of <see cref="AuthenticationResult" /> that represents the access token generated as result of a successful authenication.
        /// </returns>
        public override async Task <AuthenticationResult> AuthenticateAsync(AuthenticationParameters parameters, CancellationToken cancellationToken = default)
        {
            AuthenticationResult   authResult;
            IClientApplicationBase app;
            InteractiveParameters  interactiveParameters = parameters as InteractiveParameters;
            TcpListener            listener = null;
            string redirectUri = null;
            int    port        = 8399;

            while (++port < 9000)
            {
                try
                {
                    listener = new TcpListener(IPAddress.Loopback, port);
                    listener.Start();
                    redirectUri = $"http://localhost:{port}/";
                    listener.Stop();
                    break;
                }
                catch (Exception ex)
                {
                    WriteWarning($"Port {port} is taken with exception '{ex.Message}'; trying to connect to the next port.");
                    listener?.Stop();
                }
            }

            app = GetClient(parameters.Account, parameters.Environment, redirectUri);

            if (app is IConfidentialClientApplication)
            {
                ICustomWebUi customWebUi = new DefaultOsBrowserWebUi(interactiveParameters.Message);

                ServiceClientTracing.Information($"[InteractiveUserAuthenticator] Calling AcquireAuthorizationCodeAsync - Scopes: '{string.Join(",", parameters.Scopes)}'");

                Uri authCodeUrl = await customWebUi.AcquireAuthorizationCodeAsync(
                    await app.AsConfidentialClient().GetAuthorizationRequestUrl(parameters.Scopes).ExecuteAsync(cancellationToken).ConfigureAwait(false),
                    new Uri(redirectUri),
                    cancellationToken).ConfigureAwait(false);

                NameValueCollection queryStringParameters = HttpUtility.ParseQueryString(authCodeUrl.Query);

                ServiceClientTracing.Information($"[InteractiveUserAuthenticator] Calling AcquireTokenByAuthorizationCode - Scopes: '{string.Join(",", parameters.Scopes)}'");

                authResult = await app.AsConfidentialClient().AcquireTokenByAuthorizationCode(
                    parameters.Scopes,
                    queryStringParameters["code"]).ExecuteAsync(cancellationToken).ConfigureAwait(false);
            }
            else
            {
                ServiceClientTracing.Information(string.Format(CultureInfo.InvariantCulture, "[InteractiveUserAuthenticator] Calling AcquireTokenInteractive - Scopes: '{0}'", string.Join(",", parameters.Scopes)));

                authResult = await app.AsPublicClient().AcquireTokenInteractive(parameters.Scopes)
                             .WithCustomWebUi(new DefaultOsBrowserWebUi(interactiveParameters.Message))
                             .WithPrompt(Prompt.ForceLogin)
                             .ExecuteAsync(cancellationToken).ConfigureAwait(false);
            }

            return(authResult);
        }
Ejemplo n.º 4
0
        public void ValidateRedirectUri()
        {
            // Arrange
            var tcpInterceptor = Substitute.For <ITcpInterceptor>();

            IWebUI webUi = new DefaultOsBrowserWebUi(_platformProxy, _logger, tcpInterceptor);

            // Act
            webUi.ValidateRedirectUri(new Uri("http://localhost:12345"));
            webUi.ValidateRedirectUri(new Uri("http://127.0.0.1:54321"));

            AssertInvalidRedirectUri(webUi, "http://localhost");         // no port
            AssertInvalidRedirectUri(webUi, "http://localhost:0");       // no port
            AssertInvalidRedirectUri(webUi, "http://localhost:80");      // default port

            AssertInvalidRedirectUri(webUi, "http://www.bing.com:1234"); // not localhost
        }
        /// <summary>
        /// Acquires the Azure management token asynchronously.
        /// </summary>
        /// <param name="tenantId">The tenant identifier.</param>
        /// <param name="usePrompt">The prompt behavior. If true, raises a prompt, otherwise performs silent login.</param>
        /// <param name="userIdentifier">Optional user for which token is to be fetched.</param>
        /// <returns>AAD authentication result.</returns>
        private async Task <UserAuthenticationDetails> AcquireAzureManagementTokenAsync(
            string tenantId,
            bool usePrompt,
            string userIdentifier = null)
        {
            Guid correlationId = Guid.NewGuid();

            this.logger.LogInformation($"Acquiring token with correlation Id set to '{correlationId}'");
            try
            {
#if USEADAL
                AuthenticationContext authenticationContext = new AuthenticationContext(
                    $"{UserAuthenticator.AADLoginAuthority}{tenantId}",
                    validateAuthority: false,
                    TokenCache.DefaultShared,
                    new AzureAdHttpClientFactory())
                {
                    CorrelationId = correlationId,
                };

                AuthenticationResult authenticationResult = null;

                if (userIdentifier == null)
                {
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        Uri redirectUri = DefaultOsBrowserWebUi.UpdateRedirectUri(new Uri("http://localhost"));

                        authenticationResult = await authenticationContext.AcquireTokenAsync(
                            UserAuthenticator.AzureAADResource,
                            UserAuthenticator.PSClientId,
                            redirectUri,
                            new PlatformParameters(
                                usePrompt ? PromptBehavior.SelectAccount : PromptBehavior.Never,
                                new DefaultOsBrowserWebUi(this.logger))).ConfigureAwait(false);
                    }
                    else
                    {
                        DeviceCodeResult deviceCodeResult = await authenticationContext.AcquireDeviceCodeAsync(UserAuthenticator.AzureAADResource, UserAuthenticator.PSClientId).ConfigureAwait(false);

                        Console.WriteLine($"Interactive login required. Please enter {deviceCodeResult.UserCode} when asked for in the browser window. If a browser windows does not open or is not supported, follow the instructions below (these can be followed on any device) {Environment.NewLine}{deviceCodeResult.Message}");
                        await Task.Delay(1000).ConfigureAwait(false);

                        authenticationResult = await authenticationContext.AcquireTokenByDeviceCodeAsync(deviceCodeResult).ConfigureAwait(false);
                    }
                }
                else
                {
                    authenticationResult = await authenticationContext.AcquireTokenSilentAsync(
                        UserAuthenticator.AzureAADResource,
                        UserAuthenticator.PSClientId).ConfigureAwait(false);
                }

                return(new UserAuthenticationDetails
                {
                    AccessToken = authenticationResult.AccessToken,
                    TenantId = authenticationResult.TenantId,
                    Username = authenticationResult.UserInfo.DisplayableId,
                });
#else
                AuthenticationResult authenticationResult = null;

                if (userIdentifier == null)
                {
                    if (this.publicClientApplication.IsSystemWebViewAvailable)
                    {
                        authenticationResult = await this.publicClientApplication
                                               .AcquireTokenInteractive(new List <string>() { AzureAADResource + "/.default" })
                                               .WithAuthority($"{UserAuthenticator.AADLoginAuthority}{tenantId}", validateAuthority: false)
                                               .WithCorrelationId(correlationId)
                                               .WithPrompt(usePrompt ? Prompt.SelectAccount : Prompt.NoPrompt)
                                               .ExecuteAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        authenticationResult = await this.publicClientApplication
                                               .AcquireTokenWithDeviceCode(
                            new List <string>() { AzureAADResource + "/.default" },
                            async (deviceCodeResult) =>
                        {
                            Console.WriteLine($"Interactive login required. Please enter {deviceCodeResult.UserCode} when asked for in the browser window. If a browser windows does not open or is not supported, follow the instructions below (these can be followed on any device) {Environment.NewLine}{deviceCodeResult.Message}");
                            await Task.Delay(1000).ConfigureAwait(false);

                            try
                            {
                                // Open the browser with the url.
                                ProcessStartInfo processStartInfo = new ProcessStartInfo
                                {
                                    FileName        = deviceCodeResult.VerificationUrl,
                                    UseShellExecute = true,
                                };

                                Process.Start(processStartInfo);
                            }
                            catch (Exception)
                            {
                                Console.WriteLine($"Could not open the url for verification on this machine. Please open {deviceCodeResult.VerificationUrl} from any machine and enter code {deviceCodeResult.UserCode} when asked to do so to continue. The process will continue automatically once the login verification is done.");
                            }
                        })
                                               .WithAuthority($"{UserAuthenticator.AADLoginAuthority}{tenantId}", validateAuthority: false)
                                               .WithCorrelationId(correlationId)
                                               .ExecuteAsync().ConfigureAwait(false);
                    }
                }
                else
                {
                    authenticationResult = await this.publicClientApplication
                                           .AcquireTokenSilent(new List <string>() { AzureAADResource + "/.default" }, userIdentifier)
                                           .WithAuthority($"{UserAuthenticator.AADLoginAuthority}{tenantId}", validateAuthority: false)
                                           .WithCorrelationId(correlationId)
                                           .ExecuteAsync().ConfigureAwait(false);
                }

                return(new UserAuthenticationDetails
                {
                    AccessToken = authenticationResult.AccessToken,
                    Username = authenticationResult.Account.Username,
                    TenantId = authenticationResult.TenantId,
                });
#endif
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, $"Failed to acquire token. Correlation Id '{correlationId}'");
                throw;
            }
        }