public string CreateAuthorizationUrl()
            {
                var state = Guid.NewGuid();

                authorizationRequests[state] = new AzdoToken()
                {
                    IsPending = true
                };

                var uriBuilder = new UriBuilder(config.AuthUrl);
                NameValueCollection queryParams = HttpUtility.ParseQueryString(uriBuilder.Query ?? string.Empty);

                queryParams["client_id"]     = config.ClientId;
                queryParams["response_type"] = "Assertion";
                queryParams["state"]         = state.ToString();
                queryParams["scope"]         = config.Scope;
                queryParams["redirect_uri"]  = config.RedirectUri;

                uriBuilder.Query = queryParams.ToString();

                return(uriBuilder.ToString());
            }
            public async Task <AzdoToken> GetAccessToken(string code, Guid state)
            {
                if (ValidateCallbackValues(code, state.ToString(), out var error))
                {
                    var form = new Dictionary <string, string>()
                    {
                        { "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" },
                        { "client_assertion", config.ClientSecret },
                        { "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer" },
                        { "assertion", code },
                        { "redirect_uri", config.RedirectUri }
                    };

                    HttpClient httpClient = clientFactory.CreateClient();

                    HttpResponseMessage responseMessage = await httpClient.PostAsync(
                        "https://app.vssps.visualstudio.com/oauth2/token" ?? config.TokenUrl,
                        new FormUrlEncodedContent(form)
                        );

                    if (responseMessage.IsSuccessStatusCode)
                    {
                        var body = await responseMessage.Content.ReadAsStringAsync();

                        AzdoToken tokenModel = authorizationRequests[state];
                        JsonConvert.PopulateObject(body, tokenModel);

                        return(tokenModel);
                    }
                    else
                    {
                        error = responseMessage.ReasonPhrase;
                        var content = await responseMessage.Content.ReadAsStringAsync();

                        throw new Exception(
                                  $"{responseMessage.ReasonPhrase} {(string.IsNullOrEmpty(content) ? "" : $"({content})")}");
                    }
                }