自动执行google oAuth验证以获取授权码

时间:2018-01-04 00:03:19

标签: oauth-2.0 google-oauth2

我有一个桌面应用,需要将数据推送到谷歌表。

我可以要求用户输入使用Google OAuth身份验证所需的所有必填字段。

我希望在没有用户同意屏幕的情况下在后台进行身份验证。我尝试了不同的方法来获取身份验证代码,但它总是要求我打开同意屏幕。

我找到了一种使用无头浏览器的方法。

问题:如果我使用无头浏览器来自动执行该过程它不会使用代码调用回调uri。

1 个答案:

答案 0 :(得分:1)

所以我就是这样解决的。

  • 使用无头浏览器进行C#自动执行授权许可步骤。
  • 让一个http监听器监听redirect_uri。
  • 完成同意步骤后,您将获得http侦听器上下文请求中的授权代码。
  • 使用验证码发出访问令牌和参考令牌的请求。

以下是获取访问代码的代码示例,请按照Button_Click方法流程

    public partial class MainWindow : Window
{
    private TokenDetails m_TokenDetails = new TokenDetails();

    const string TOKEN_REDIRECT_URI          = "http://localhost:5501/";
    const string GRANT_TYPE = "authorization_code";
    const string REFRESH_TOKEN_GRANT_TYPE = "refresh_token";

    const string REDIRECT_URI = "http://localhost:5500/";
    const string CLIENT_ID             = "CLIENT_ID"; // This should be real Client ID
    const string CLIENT_SECRET         = "CLIENT_SECRET"; // This should be real Client Secret
    const string CODE_CHALLANGE        = "CODE_CHALLANGE"; // This should be real Code Challange
    const string CODE_CHALLANGE_METHOD = "plain";
    const string RESPONSE_TYPE         = "code";
    const string SCOPE                 = "SCOPE"; // This should be real scope

    public MainWindow()
    {
        InitializeComponent();

    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (!HttpListener.IsSupported)
        {
            Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
            return;
        }

        #region AuthCode

        HttpListener listener = StartHttpListener(REDIRECT_URI);

        GetAuthCode(listener);

        ((IDisposable)listener).Dispose();

        #endregion

        string tokenUri = $"https://www.googleapis.com/oauth2/v4/token?code={m_TokenDetails.Auth_Code}&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&redirect_uri={REDIRECT_URI}&grant_type={GRANT_TYPE}&code_verifier={CODE_CHALLANGE}";

        GetTokenDetails(tokenUri);
    }

    private void GetTokenDetails(string tokenUri)
    {
        HttpClient tokenClient = new HttpClient();
        tokenClient.DefaultRequestHeaders.Clear();

        var response = tokenClient.PostAsync(tokenUri, null).Result;
        string tokenJson = "";
        if (response.IsSuccessStatusCode)
        {
            tokenJson = response.Content.ReadAsStringAsync().Result;
            JObject tokenObj = JObject.Parse(tokenJson);

            textBlock1.Text = tokenObj.ToString();

            m_TokenDetails.Access_Token = tokenObj.SelectToken("access_token").ToString();
            m_TokenDetails.ExpiresIn = Convert.ToInt32(tokenObj.SelectToken("expires_in"));
            m_TokenDetails.Refresh_Token = tokenObj.SelectToken("refresh_token").ToString();
            m_TokenDetails.TokenType = tokenObj.SelectToken("token_type").ToString();
        }
    }

    private void GetAuthCode(HttpListener listener)
    {
        Task.Run(new Action(async () =>
        {
            try
            {
                NHtmlUnit.WebClient c = new NHtmlUnit.WebClient();
                string uri = $"https://accounts.google.com/o/oauth2/v2/auth?code_challenge={CODE_CHALLANGE}&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&response_type={RESPONSE_TYPE}&scope={SCOPE}&code_challenge_method={CODE_CHALLANGE_METHOD}";
                var consentpage = (NHtmlUnit.Html.HtmlPage)c.GetPage(uri);

                var emailInput = consentpage.GetElementById("Email");
                var nextButton = consentpage.GetElementById("next");

                emailInput.SetAttribute("value", "test@gmail.com");

                var pwdPage  = (HtmlPage)nextButton.Click();
                var pwdInput = pwdPage.GetElementById("Passwd");
                pwdInput.SetAttribute("value", "test");
                var signinBtn = pwdPage.GetElementById("signIn");


                var allowPAge = (HtmlPage)signinBtn.Click();
                var allowbtn  = allowPAge.GetElementById("submit_approve_access");

                var form  = allowPAge.GetElementsByTagName("form");
                var formAction =  ((HtmlElement)form[0]).GetAttribute("action");

                Debug.WriteLine("Making http call");

                HttpClient client = new HttpClient();
                var r = await client.PostAsync(formAction, null);
                await Task.Delay(1000);
                Debug.WriteLine("Request sent..");
                client.Dispose();
                Debug.WriteLine("client disposed...");
                allowbtn.Click();
                Debug.WriteLine("Button clicked...");
            }
            catch
            {
            }
        }));

        Debug.WriteLine("listener waiting for http context");
        listener.GetContextAsync().ContinueWith(async (t) =>
        {
            Debug.WriteLine("Request received...");
            var context = await t;
            var req = t.Result.Request;
            m_TokenDetails.Auth_Code = req.QueryString[0];
        }).Wait();
    }

    private static HttpListener StartHttpListener(string prefix)
    {
        HttpListener listener = new HttpListener();

        listener.Prefixes.Add(prefix);
        listener.Start();
        return listener;
    }