在HttpClient中向Google Oauth2 SSO发送Rest请求时,如何解决“错误请求”错误

时间:2019-03-28 10:53:55

标签: c# asp.net rest oauth-2.0

我正在尝试学习如何实现Google的Oauth2 SSO登录功能。到目前为止,我已经到了一切正常的地步,只是当我尝试使用C#中的REST来向“ https://accounts.google.com/o/oauth2/token”发送请求以获取Access_code / Token时。我已经在google上注册了我的本地主机和相应的端口,并设法使POST请求可以在POSTMAN中工作,但是当我尝试在C#中发送请求时,HttpRequestMessage返回了400个错误请求。

首先,我有一个Authorization.aspx页面,该页面运行一个命令,该命令将用户重定向到用户登录的google授权页面,然后重定向到我的页面http://localhost:64716/GoogleCallBack.aspx,该页面获取响应。在该页面中,它获取授权码,并尝试将POST请求发送到基本URL。我尝试过在可以工作的POSTMAN中运行它(尽管仅使用新的授权代码)。因此,我知道问题出在我的C#代码上。我尝试使用webrequest,也尝试将媒体类型更改为application / Json和application / x-www-form-urlencoded

    protected void Page_Load(object sender, EventArgs e)
    {

        string Error = Request.QueryString["error"];

        string Code = Request.QueryString["code"];
        if (Error != null) { }
        else if (Code != null)
        {

            string UserId = Request.QueryString["state"];
            int Id = Convert.ToInt32(UserId);
            string AccessToken = string.Empty;
            string RefreshToken = ExchangeAuthorizationCode(Id, Code, out AccessToken);
            string Url = "Authorize.aspx?UserId=" + UserId;
            Response.Redirect(Url, true);
        }
    }
    private string ExchangeAuthorizationCode(int userId, string code, out string accessToken)
    {
        string baseurl = "https://accounts.google.com/o/oauth2/token";
        accessToken = string.Empty;
        string ClientSecret = ConfigurationManager.AppSettings["ClientSecrete"];
        string ClientId = ConfigurationManager.AppSettings["ClientId"];

        string RedirectUrl = "http://localhost:64716/GoogleCallBack.aspx";

        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(baseurl);
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/Json"));

            var nvc = new List<KeyValuePair<string, string>>();
            nvc.Add(new KeyValuePair<string, string>("Code", code));
            nvc.Add(new KeyValuePair<string, string>("Client_id", ClientId));
            nvc.Add(new KeyValuePair<string, string>("Client_secret", ClientSecret));
            nvc.Add(new KeyValuePair<string, string>("Redirect_uri", RedirectUrl));
            nvc.Add(new KeyValuePair<string, string>("Grant_type", "authorization_code"));
            nvc.Add(new KeyValuePair<string, string>("access_type", "offline"));

            var req = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress) { Content = new FormUrlEncodedContent(nvc) };
            var resres = client.SendAsync(req).Result;

            return "temp";

        }

    }

我希望我的回复是状态码200,带有来自Google的access_token(就像在Postman中一样)

1 个答案:

答案 0 :(得分:0)

[已解决]这就是我所做的(在一些朋友的帮助下)

  1. 将标头更改为JSON

  2. 将基本URI移至PostAsync()

  3. 一旦我更改了所有内容,就可以看到错误出在redirect_Uri中,然后我将其更改为与邮递员中的错误匹配。现在可以了

    protected void Page_Load(object sender, EventArgs e)
        {
            //you will get this, when any error will occur while authorization otherwise null    
            string Error = Request.QueryString["error"];
            //authorization code after successful authorization    
            string Code = Request.QueryString["code"];
            if (Error != null) { }
            else if (Code != null)
            {
                //Remember, we have set userid in State    
                string UserId = Request.QueryString["state"];
                //Get AccessToken    
                int Id = Convert.ToInt32(UserId);
                string AccessToken = string.Empty;
                string RefreshToken = ExchangeAuthorizationCode(Id, Code, out AccessToken);
                //saving refresh token in database    
                SaveRefreshToken(Id, RefreshToken);
                //Get Email Id of the authorized user    
                string EmailId = FetchEmailId(AccessToken);
                //Saving Email Id    
                SaveEmailId(UserId, EmailId);
                //Redirect the user to Authorize.aspx with user id    
                string Url = "Authorize.aspx?UserId=" + UserId;
                Response.Redirect(Url, true);
            }
        }
    
        private string ExchangeAuthorizationCode(int userId, string code, out string accessToken)
        {
            string baseurl = "https://accounts.google.com/o/oauth2/token";
            accessToken = string.Empty;
            string ClientSecret = ConfigurationManager.AppSettings["ClientSecrete"];
            string ClientId = ConfigurationManager.AppSettings["ClientId"];
            // //get this value by opening your web app in browser.    
            string RedirectUrl = "http://localhost:64716/GoogleCallback.aspx"; //I changed this to match the one in Postman
    
            using (var client = new HttpClient())
            {
                //client.BaseAddress = new Uri("https://accounts.google.com/o/oauth2"); //I replaced the Uri to "var result = client.PostAsync("https://accounts.google.com/o/oauth2/token", nvc).Result;"
                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // I made this JSON
                // I removed this "client.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");"
    
                var nvc = new FormUrlEncodedContent(new[] {
                new KeyValuePair<string, string>("grant_type", "authorization_code"),
                new KeyValuePair<string, string>("code", code),
                new KeyValuePair<string, string>("client_id", ClientId),
                new KeyValuePair<string, string>("client_secret", ClientSecret),
                new KeyValuePair<string, string>("redirect_uri", RedirectUrl),
                new KeyValuePair<string, string>("access_type", "offline")
                });
    
                var result = client.PostAsync("https://accounts.google.com/o/oauth2/token", nvc).Result;
    
                var resultContent = result.Content.ReadAsStringAsync();
    
                var tokenResponse = JsonConvert.DeserializeObject<Authorization_request_body>(resultContent.ToString());
    
                return "temp";
    
                }
    
            }