internal async Task <DeviceAuthorizationResponse> BeginLogin()
        {
            var client = _clientFactory.CreateClient();

            var disco = await HttpClientDiscoveryExtensions.GetDiscoveryDocumentAsync(client, _authConfigurations.Value.StsServer);

            if (disco.IsError)
            {
                throw new ApplicationException($"Status code: {disco.IsError}, Error: {disco.Error}");
            }

            var deviceAuthorizationRequest = new DeviceAuthorizationRequest
            {
                Address  = disco.DeviceAuthorizationEndpoint,
                ClientId = "deviceFlowWebClient"
            };

            deviceAuthorizationRequest.Scope = "email profile openid";
            var response = await client.RequestDeviceAuthorizationAsync(deviceAuthorizationRequest);

            if (response.IsError)
            {
                throw new Exception(response.Error);
            }

            return(response);
        }
        public async Task Http_request_should_have_correct_format()
        {
            var handler = new NetworkHandler(HttpStatusCode.NotFound, "not found");

            var client  = new HttpClient(handler);
            var request = new DeviceAuthorizationRequest
            {
                Address  = Endpoint,
                ClientId = "client"
            };

            request.Headers.Add("custom", "custom");
            request.Properties.Add("custom", "custom");

            var _ = await client.RequestDeviceAuthorizationAsync(request);

            var httpRequest = handler.Request;

            httpRequest.Method.Should().Be(HttpMethod.Post);
            httpRequest.RequestUri.Should().Be(new Uri(Endpoint));

            var headers = httpRequest.Headers;

            headers.Count().Should().Be(3);
            headers.Should().Contain(h => h.Key == "custom" && h.Value.First() == "custom");

            var properties = httpRequest.Properties;

            properties.Count.Should().Be(1);

            var prop = properties.First();

            prop.Key.Should().Be("custom");
            ((string)prop.Value).Should().Be("custom");
        }
        public async Task Repeating_a_request_should_succeed()
        {
            var document = File.ReadAllText(FileName.Create("success_device_authorization_response.json"));
            var handler  = new NetworkHandler(document, HttpStatusCode.OK);

            var request = new DeviceAuthorizationRequest
            {
                Address  = Endpoint,
                ClientId = "client"
            };

            var client   = new HttpClient(handler);
            var response = await client.RequestDeviceAuthorizationAsync(request);

            response.IsError.Should().BeFalse();
            response.ErrorType.Should().Be(ResponseErrorType.None);
            response.HttpStatusCode.Should().Be(HttpStatusCode.OK);

            response.DeviceCode.Should().Be("GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8");
            response.UserCode.Should().Be("WDJB-MJHT");
            response.VerificationUri.Should().Be("https://www.example.com/device");
            response.VerificationUriComplete.Should().Be("https://www.example.com/device?user_code=WDJB-MJHT");

            response.ExpiresIn.Should().Be(1800);
            response.Interval.Should().Be(10);

            // repeat
            response = await client.RequestDeviceAuthorizationAsync(request);

            response.IsError.Should().BeFalse();
            response.ErrorType.Should().Be(ResponseErrorType.None);
            response.HttpStatusCode.Should().Be(HttpStatusCode.OK);

            response.DeviceCode.Should().Be("GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8");
            response.UserCode.Should().Be("WDJB-MJHT");
            response.VerificationUri.Should().Be("https://www.example.com/device");
            response.VerificationUriComplete.Should().Be("https://www.example.com/device?user_code=WDJB-MJHT");

            response.ExpiresIn.Should().Be(1800);
            response.Interval.Should().Be(10);
        }
示例#4
0
        public async Task <DeviceAuthorizationResponse> GetDeviceCode()
        {
            var client = _clientFactory.CreateClient();
            var disco  = await GetDiscoveryEndpoints(client);

            var deviceAuthorizationRequest = new DeviceAuthorizationRequest
            {
                Address  = disco.DeviceAuthorizationEndpoint,
                ClientId = _azureAdConfiguration.ClientId
            };

            deviceAuthorizationRequest.Scope = "email profile openid";
            var response = await client.RequestDeviceAuthorizationAsync(deviceAuthorizationRequest);

            if (response.IsError)
            {
                throw new Exception(response.Error);
            }

            return(response);
        }
示例#5
0
        private static async Task <DeviceAuthorizationResponse> RequestAuthorizationAsync()
        {
            var disco = await _cache.GetAsync();

            if (disco.IsError)
            {
                throw new InvalidOperationException(disco.Error);
            }

            using (var httpClient = new HttpClient())
            {
                using (var deviceAuthorizationRequest = new DeviceAuthorizationRequest {
                    Address = disco.DeviceAuthorizationEndpoint, ClientId = "device"
                })
                {
                    var response = await httpClient.RequestDeviceAuthorizationAsync(deviceAuthorizationRequest);

                    if (response.IsError)
                    {
                        throw new InvalidOperationException(response.Error);
                    }

                    WriteLine($"user code   : {response.UserCode}");
                    WriteLine($"device code : {response.DeviceCode}");
                    WriteLine($"URL         : {response.VerificationUri}");
                    WriteLine($"Complete URL: {response.VerificationUriComplete}");

                    WriteLine($"{Environment.NewLine}Press enter to launch browser ({response.VerificationUri})");
                    ReadLine();

                    Process.Start(new ProcessStartInfo(response.VerificationUriComplete)
                    {
                        UseShellExecute = true
                    });

                    return(response);
                }
            }
        }
示例#6
0
    protected virtual async Task <TokenResponse> RequestDeviceAuthorizationAsync(HttpClient httpClient, IdentityClientConfiguration configuration)
    {
        var discoveryResponse = await GetDiscoveryResponse(configuration);

        var request = new DeviceAuthorizationRequest()
        {
            Address      = discoveryResponse.DeviceAuthorizationEndpoint,
            Scope        = configuration.Scope,
            ClientId     = configuration.ClientId,
            ClientSecret = configuration.ClientSecret,
        };

        IdentityModelHttpRequestMessageOptions.ConfigureHttpRequestMessage?.Invoke(request);

        await AddParametersToRequestAsync(configuration, request);

        var response = await httpClient.RequestDeviceAuthorizationAsync(request);

        if (response.IsError)
        {
            throw new AbpException(response.ErrorDescription);
        }

        Logger.LogInformation($"First copy your one-time code: {response.UserCode}");
        Logger.LogInformation($"Open {response.VerificationUri} in your browser...");

        for (var i = 0; i < ((response.ExpiresIn ?? 300) / response.Interval + 1); i++)
        {
            await Task.Delay(response.Interval * 1000);

            var tokenResponse = await httpClient.RequestDeviceTokenAsync(new DeviceTokenRequest
            {
                Address      = discoveryResponse.TokenEndpoint,
                ClientId     = configuration.ClientId,
                ClientSecret = configuration.ClientSecret,
                DeviceCode   = response.DeviceCode
            });

            if (tokenResponse.IsError)
            {
                switch (tokenResponse.Error)
                {
                case "slow_down":
                case "authorization_pending":
                    break;

                case "expired_token":
                    throw new AbpException("This 'device_code' has expired. (expired_token)");

                case "access_denied":
                    throw new AbpException("User denies the request(access_denied)");
                }
            }

            if (!tokenResponse.IsError)
            {
                return(tokenResponse);
            }
        }

        throw new AbpException("Timeout!");
    }
示例#7
0
        protected async override Task <int> ExecuteCommand(LoginCommand arguments)
        {
            Console.WriteLine("Logging in...");
            logger.LogInformation("Logging in... with {Arguments}", arguments);
            if (!arguments.NoCache)
            {
                var userToken = await tokenStorage.LoadUserTokenAsync();

                logger.LogInformation("Loaded {UserToken}", userToken);
                if (userToken != null)
                {
                    userToken = await refreshTokenHandler.RefreshTokenAsync(userToken);

                    logger.LogInformation("Refreshed {UserToken}", userToken);
                    if (userToken != null)
                    {
                        Console.WriteLine("Login successful!");
                        logger.LogInformation("Login successful!");
                        await StoreToken(arguments, userToken);

                        return(0);
                    }
                }
            }

            var disco = await discoveryProvider.FetchDiscoveryDocument();

            var request = new DeviceAuthorizationRequest
            {
                Address  = disco.DeviceAuthorizationEndpoint,
                ClientId = configurationProvider.ClientId,
                Scope    = configurationProvider.Scope
            };

            logger.LogInformation("RequestDeviceAuthorizationAsync {Request}", request);

            var result = await httpClient.RequestDeviceAuthorizationAsync(request);

            if (result.IsError)
            {
                Console.WriteLine(result.Error);
                var ex = new Exception(result.Error);
                logger.LogError(ex, "RequestDeviceAuthorizationAsync {Request} {Response}", request, result);
                throw ex;
            }
            else
            {
                logger.LogInformation("RequestDeviceAuthorizationAsync {Request} {Response}", request, result);
            }

            Console.WriteLine($"Visit: {result.VerificationUri}");
            Console.WriteLine();
            Console.WriteLine("And enter this code");
            Console.WriteLine("-------------------");
            Console.WriteLine($"-    {result.UserCode}    -");
            Console.WriteLine("-------------------");

            var fetchToken = true;
            var interval   = (result.Interval == 0 ? 5 : result.Interval) * 1000;
            var spinner    = new ConsoleSpinner();

            while (fetchToken)
            {
                spinner.Turn();
                Console.Write(" Fetching token....");
                var tokenResponse = await httpClient.RequestDeviceTokenAsync(new DeviceTokenRequest
                {
                    Address    = disco.TokenEndpoint,
                    ClientId   = configurationProvider.ClientId,
                    DeviceCode = result.DeviceCode,
                });

                if (tokenResponse.IsError)
                {
                    if (tokenResponse.Error == "authorization_pending" || tokenResponse.Error == "slow_down")
                    {
                        await Task.Delay(interval);
                    }
                    else
                    {
                        spinner.ClearLine();
                        Console.WriteLine(tokenResponse.Error);
                        throw new Exception(tokenResponse.Error);
                    }
                }
                else
                {
                    var userToken = new UserToken(
                        tokenResponse.AccessToken,
                        tokenResponse.RefreshToken,
                        tokenResponse.IdentityToken,
                        DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn)
                        );

                    spinner.ClearLine();

                    Console.WriteLine("Login successful!");

                    await StoreToken(arguments, userToken);

                    return(0);
                }
            }

            return(0);
        }
示例#8
0
    /// <summary>
    /// Sends a userinfo request.
    /// </summary>
    /// <param name="client">The client.</param>
    /// <param name="request">The request.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns></returns>
    public static async Task <DeviceAuthorizationResponse> RequestDeviceAuthorizationAsync(this HttpMessageInvoker client, DeviceAuthorizationRequest request, CancellationToken cancellationToken = default)
    {
        var clone = request.Clone();

        clone.Parameters.AddOptional(OidcConstants.AuthorizeRequest.Scope, request.Scope);
        clone.Method = HttpMethod.Post;
        clone.Prepare();

        HttpResponseMessage response;

        try
        {
            response = await client.SendAsync(clone, cancellationToken).ConfigureAwait();
        }
        catch (Exception ex)
        {
            return(ProtocolResponse.FromException <DeviceAuthorizationResponse>(ex));
        }

        return(await ProtocolResponse.FromHttpResponseAsync <DeviceAuthorizationResponse>(response).ConfigureAwait());
    }