我有一个桌面应用,需要将数据推送到谷歌表。
我可以要求用户输入使用Google OAuth身份验证所需的所有必填字段。
我希望在没有用户同意屏幕的情况下在后台进行身份验证。我尝试了不同的方法来获取身份验证代码,但它总是要求我打开同意屏幕。
我找到了一种使用无头浏览器的方法。
问题:如果我使用无头浏览器来自动执行该过程它不会使用代码调用回调uri。
答案 0 :(得分:1)
所以我就是这样解决的。
以下是获取访问代码的代码示例,请按照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;
}