如何获取谷歌OAuth的访问令牌?

11

我正在使用C# (ASP.NET)。我想在我的应用程序中使用Google OAuth来访问用户的个人资料。我已经成功获取了授权码,但在获取访问令牌时出现了问题。

我更喜欢使用Google教程。在教程中,我读到必须向Google发送请求并获取响应。为此,我使用 System.Net.HttpWebRequest / HttpWebResponse (这样做正确吗?)。我使用的代码是...

byte[] buffer = Encoding.ASCII.GetBytes("?code=" + code + "&client_id=xxx&client_secret=xxx&redirect_uri=xxxx&grant_type=authorization_code");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://accounts.google.com");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = buffer.Length;

Stream strm = req.GetRequestStream();
strm.Write(buffer, 0, buffer.Length);
strm.Close();

HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Response.Write(((HttpWebResponse)resp).StatusDescription);

但是,我遇到了这个错误:

远程服务器返回了一个错误:(405) 方法不允许。

更新:这里的变量 code 是授权码。


1
为什么不使用https://code.google.com/p/google-api-dotnet-client/wiki/OAuth2? - user854301
@user854301 我可以提供参考,但我想知道使用 HttpWebRequest/Response 是否正确?我能否从 HttpWebRequest 向谷歌发送请求。 - Sagar
你的缓冲区中的“code”是什么? - Apoorva
@Apoorva 这是一个授权码。 - Sagar
如何获取授权码...您能告诉我吗?我不知道。 - user4736499
本指南包括授权代码流程 https://www.c-sharpcorner.com/article/implementing-oauth2-0-authorization-for-google-in-asp-net/ - user942620
6个回答

8

我认为您将POST请求发送到了错误的端点,正确的端点是https://accounts.google.com/o/oauth2/token


2
我使用了这个,但是它显示了其他错误。现在的错误是 远程服务器返回错误:(400)错误请求。 我做错了什么? - Sagar
深入了解异常的详细信息,完整的错误消息将告诉您请求出了什么问题。 - Claudio Cherubino

4

由于我在实现Google身份验证的过程中也遇到了类似的问题,因此我会发布可行的代码。最后提到的问题:错误(400)“Bad request”可能是由上述代码中前导的“?”引起的。

 string codeClient = "code="+ t +"&client_id=number.apps.googleusercontent.com&";
 string secretUri = "client_secret=yoursecret&" + "redirect_uri=path&"
      + "grant_type=authorization_code";
 postString = codeClient + secretUri;

 string url = "https://accounts.google.com/o/oauth2/token";

 HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url.ToString());
 request.Method = "POST";
 request.ContentType = "application/x-www-form-urlencoded";

 UTF8Encoding utfenc = new UTF8Encoding();
 byte[] bytes = utfenc.GetBytes(postString);
 Stream os = null;
 try
 {
      request.ContentLength = bytes.Length;
      os = request.GetRequestStream();
      os.Write(bytes, 0, bytes.Length);
 }
 catch
 { }

 try
 {
      HttpWebResponse webResponse = (HttpWebResponse) request.GetResponse();
      Stream responseStream = webResponse.GetResponseStream();
      StreamReader responseStreamReader = new StreamReader(responseStream);
      result = responseStreamReader.ReadToEnd();//parse token from result

@Sahil,请确保oauth的URL是有效的。请注意,我将近5年前使用了这段代码片段。 - Neno
@CyberNinja,请在同一论坛中查看我的代码。它完美地运行。如果有其他问题,请告诉我。 - Sahil Bhatia
@SahilBhatia 我的意思是,你如何获取作为参数传递的代码,例如,你如何通过 .net 代码向 Google 请求它?我知道你可以在浏览器中将其作为请求类型的 URL 请求,但这将要求我登录。 - CyberNinja
我尝试了类似的方式,但是得到了糟糕的响应,有人可以帮忙吗? - Techiemanu

2

我的代码可以工作,我在上面两行中犯了错误。应该是这样的

byte[] buffer = Encoding.ASCII.GetBytes("code=" + code + "&client_id=xxx&client_secret=xxx&redirect_uri=xxxx&grant_type=authorization_code");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");

剩余的代码是正确的。


@Viktor:我注意到你的客户端ID客户端密钥都包含在缓冲区中。我的托管网站没有SSL。你知道Google是否会接受来自非SSL连接的Web请求吗?显然,这是不安全的,有人可能会窃取我的凭据,但我不知道有什么解决办法。 - user153923
我停止阅读在“没有 SSL”那里。请使用 SSL。 - thomasgalliker

0
public string ReceiveTokenGmail(string code, string GoogleWebAppClientID, string GoogleWebAppClientSecret, string RedirectUrl)
{
    string postString = "code=" + code + "&client_id=" + GoogleWebAppClientID + @"&client_secret=" + GoogleWebAppClientSecret  + "&redirect_uri=" + RedirectUrl;

    string url = "https://accounts.google.com/o/oauth2/token";

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.ToString());
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";

    UTF8Encoding utfenc = new UTF8Encoding();
    byte[] bytes = utfenc.GetBytes(postString);
    Stream os = null;
    try
    {
        request.ContentLength = bytes.Length;
        os = request.GetRequestStream();
        os.Write(bytes, 0, bytes.Length);
    }
    catch
    { }
    string result = "";

    HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
    Stream responseStream = webResponse.GetResponseStream();
    StreamReader responseStreamReader = new StreamReader(responseStream);
    result = responseStreamReader.ReadToEnd();

    return result;
}

我该如何从谷歌获取认证代码?我想使用您的代码,这样我就不必使用key.json文件,而是只需为我的客户端ID和客户端密钥使用应用程序配置。如果您能分享如何获取授权代码,那就太棒了。 - CyberNinja

0

找到正确且简单的方式通过授权码获取访问令牌,真是出乎意料的困难。(尤其是因为我花了一些时间,即使有了正确的代码,也会因为我的授权码在搜索时过期而出现“invalid_grant”错误 :) )

以下是代码:

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
  new GoogleAuthorizationCodeFlow.Initializer
  {
    ClientSecrets = new ClientSecrets()
    {
      // Use ones from "Web SDK configuration" section if you created your app in Firebase.
      ClientId = "…",
      ClientSecret = "…"
    },
    Scopes = new[] { "email" },
  }
);

TokenResponse token = await  flow.ExchangeCodeForTokenAsync(string.Empty, "4/…", string.Empty, CancellationToken.None);

正如您所看到的,userId可以为空,同样也可以是redirectUri。 不要忘记添加Google.Apis.Auth Nuget包引用。


0

原始请求似乎有些过时了。但我发现谷歌的代码示例包含大量难以与基本操作分离的“最佳实践”清理代码。

我最近发布了一份文档,将所有REST操作表示为curl命令。虽然很难精通每种语言,但curl似乎是通用的。大多数人都知道它-否则,它很容易掌握。在我的curl示例中,-d标志表示POST操作。否则,参数将附加到URL上。

http://www.tqis.com/eloquency/googlecalendar.htm


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接