当前位置: 首页 > 知识库问答 >
问题:

如何使用access_token查询gmail api

东方英豪
2023-03-14

我有一个网络应用程序,用户在登录我们的系统后,可以进入一个页面授权gmail访问,通过谷歌的整个OAuth过程。这个过程完成了,我收到了access_token和refresh_token,还解析了用户子属性的id_token,并将其保存到数据库中。这样做的目的是,通过用户授权我们的应用程序,我们然后使用控制台应用程序中的访问和刷新令牌来检索他们的电子邮件,并将其与我们的内部系统同步。

在google dev控制台中,我创建了一个带有适当重定向uris的web应用程序凭据。浏览器授权过程一切正常。然而,当我使用访问令牌运行控制台应用程序时,它会打开一个浏览器窗口,上面有一个谷歌错误

Error: redirect_uri_mismatch

The redirect URI in the request, http://127.0.0.1:57590/authorize/, does not match the ones authorized for the OAuth client.

由于这是一个控制台应用程序,没有重定向uri。这让我想知道是否需要将凭据设置为“其他”应用程序类型。我创建了一个新的凭据,并用新的凭据替换了我的网络应用程序中的客户端和秘密。当我经历登录到我们的系统,然后访问授权页面的过程时,一切都很好。然后我回到我的控制台应用程序(现在使用更新的id),当它运行时,它会打开一个浏览器窗口,要求我登录谷歌并再次验证它!我已经在第一步做到了。由于这是在应用服务器上运行的控制台应用,用户无法与它交互以授权访问...我以为这就是访问令牌的全部意义!?

这是我的代码

处理授权的Web应用控制器。

public class GoogleController : Controller
{
    private readonly CredentialService _credentialService;
    private readonly GoogleEndpoints _endpoints;

    private string AuthorizeUrl{ get { return ...; }}
    private string AuthorizeResponseUrl{ get { return ...; }}
    private string SaveResponseUrl{ get { return ...; }}

    public GoogleController()
    {
        _endpoints = new GoogleEndpoints();
        _credentialService = new CredentialService(new CredentialRepository(ConnectionStrings.GeneralInfo));
    }

    public void Authorize()
    {
        if (Session["UserID"] == null || Session["Email"] == null)
        {
            Response.Redirect("~/Login.aspx", true);
            Session["LoginSource"] = AuthorizeUrl;
            Response.End();
        }
        else
        {
            if (Session["SessionId"] == null || Session["SessionId"].ToString().Trim().Length == 0)
                Session["SessionId"] = _credentialService.CreateSessionId(Session["UserID"].To<int>());


            var url = _endpoints.AuthorizationEndpoint + "?" +
                      "client_id=" + APIConstants.GMailApiKey + "&" +
                      "response_type=code&" +
                      "scope=openid%20email https://www.googleapis.com/auth/gmail.readonly&" +
                      "redirect_uri=" + AuthorizeResponseUrl + "&" +
                      "state=" + Session["SessionId"] + "&" +
                      "login_hint=" + Session["Email"] + "&" +
                      "access_type=offline&prompt=consent";

            Response.Redirect(url);
        }
    }

    public ActionResult AuthorizeResponse()
    {
        var state = Request.QueryString["state"];
        if (state == Session["SessionId"].ToString())
        {
            var code = Request.QueryString["code"];
            var values = new Dictionary<string, object>
            {
                {"code", code},
                {"redirect_uri", AuthorizeResponseUrl},
                {"client_id", APIConstants.GMailApiKey},
                {"client_secret", APIConstants.GmailApiSecret},
                {"grant_type", "authorization_code"},
                {"scope", ""}
            };

            var webmethods = new WebMethods();
            var tokenResponse = webmethods.Post(_endpoints.TokenEndpoint, values);

            var jobject = JObject.Parse(tokenResponse);
            var access_token = jobject.SelectToken("access_token");
            var refresh_token = jobject.SelectToken("refresh_token");
            var id_token = jobject.SelectToken("id_token");

            if (access_token == null || access_token.ToString().Trim().Length == 0)
            {
                var emailService = new EmailRouterService(new EmailRouterRepository(ConnectionStrings.EmailRouter));
                emailService.SendEmail(new Email
                {
                    Body = tokenResponse,
                    Subject = "Error setting up google for " + Session["Email"] + ". ",
                    FromAddress = "TenixErrors@synergydatasystems.com",
                    ToAddress = "tendevs@synergydatasystems.com"
                });

                return View(new GoogleAuthResponse(tokenResponse, false));
            }


            var idTokenEls = id_token.ToString().Split('.');
            var idTokenString = base64Decode(idTokenEls[1]);
            var id_token_json = JObject.Parse(idTokenString);

            var credentials = _credentialService.GetUserCredentials(Session["SessionId"].ToString());

            credentials.AccessToken = access_token.ToString();
            credentials.RefreshToken = refresh_token.ToString();
            credentials.TEEmployeeId = Session["UserId"].To<int>();
            credentials.EmailAddress = id_token_json.SelectToken("email").ToString();
            credentials.GoogleSubKey = id_token_json.SelectToken("sub").ToString();


            _credentialService.SaveUserCredentials(credentials);

            return View(new GoogleAuthResponse("Integration successful!", true));
        }

        return View(new GoogleAuthResponse("Missing state information.", false));
    }

    public string base64Decode(string data)
    {
        ....
    }
}

控制台应用程序正在使用。net谷歌api库。

public class GmailUserSync
{
    private readonly CredentialService _credentialService;

    public GmailUserSync(CredentialService credentialService)
    {
        _credentialService = credentialService;
    }

    public void SyncThreads()
    {
        var secrets = new ClientSecrets
        {
            ClientId = APIConstants.GMailApiKey,
            ClientSecret = APIConstants.GmailApiSecret
        };

        var credentials = _credentialService.GetAllCredentials();

        foreach (var c in credentials)
        {
            var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                secrets,
                new[] { GmailService.Scope.GmailReadonly },
                c.GoogleSubKey,
                CancellationToken.None,
                new TenixDataStore(_credentialService)).Result;

            var service = new GmailService(new BaseClientService.Initializer
            {
                HttpClientInitializer = credential,
                ApplicationName = "Gmail Integration"
            });

            var request = service.Users.Messages.List("me");

            // List messages.
            var messages = request.Execute().Messages;
            Console.WriteLine("Messages:");

            if (messages != null && messages.Count > 0)
                foreach (var message in messages)
                {
                    Console.WriteLine("From : " + message.ThreadId);
                }

            else
                Console.WriteLine("No labels found.");
        }

        Console.Read();
    }
}

以及我对IDataStore的实施。

public class TenixDataStore : IDataStore
{
    private readonly ICredentialService _service;

    public TenixDataStore(ICredentialService credentialService)
    {
        _service = credentialService;
    }

    public Task StoreAsync<T>(string key, T value)
    {
        if (string.IsNullOrEmpty(key))
            throw new ArgumentException("Key MUST have a value");

        var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);
        var jObject = JObject.Parse(serialized);

        var access_token = jObject.SelectToken("access_token");
        var refresh_token = jObject.SelectToken("refresh_token");

        if (access_token == null)
            throw new ArgumentException("Missing access token");

        if (refresh_token == null)
            throw new ArgumentException("Missing refresh token");

        var credential = _service.GetUserCredentialsFromGoogleSubId(key);

        credential.AccessToken = (string) access_token;
        credential.RefreshToken = (string) refresh_token;

        _service.SaveUserCredentials(credential);

        return Task.Delay(0);
    }

    public Task DeleteAsync<T>(string key)
    {
        return Task.Delay(0);
    }

    public Task<T> GetAsync<T>(string googleSubId)
    {
        var credentials = _service.GetUserCredentialsFromGoogleSubId(googleSubId);
        var completionSource = new TaskCompletionSource<T>();

        if (!string.IsNullOrEmpty(credentials.RefreshToken))
        {
            var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(credentials);
            completionSource.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(jsonData));
        }
        else
            completionSource.SetResult(default(T));

        return completionSource.Task;
    }

    public Task ClearAsync()
    {
        return Task.Delay(0);
    }
}

IDataStore中的GetAsync方法正在向GoogleWebAuthorizationBroker返回访问令牌并刷新令牌凭据。AuthorizeAsync和之后,这是当一个新的浏览器打开,要求我授权的应用程序。

那么,我应该在谷歌控制台中将其设置为web应用类型还是其他类型?既然我在任何一方面都遇到了问题,我做错了什么?

共有1个答案

刘和玉
2023-03-14

您从Google Dev控制台生成的每个OauClientID都有一个redirect_uri。

 类似资料:
  • 我正在尝试使用jQuery获取access_token。问题是,我无法获得该令牌(服务器运行在localhost上)。服务器运行良好(我在postman中尝试过),但在jQuery中无法得到它。浏览器在单击按钮后写入。 由于MIME类型(“Application/JSON”)不匹配(x-content-type-options:nosniff),来自“http://localhost:8080/o

  • 本文向大家介绍如何使用LIMIT查询MongoDB?,包括了如何使用LIMIT查询MongoDB?的使用技巧和注意事项,需要的朋友参考一下 使用limit()方法查询MongoDB。让我们创建一个包含文档的集合 在find方法的帮助下显示集合中的所有文档- 这将产生以下输出- 以下是在MongoDB中使用LIMIT的查询- 这将产生以下输出-

  • 问题内容: 谁能帮助我获取下面提到的JPA查询的JPA标准查询。 问题答案: 假设Person与语言有关,这就是您在较早的Hibernate中所做的事情: 我第一次尝试使用JPA 2.0: 请让我知道这是否适合您。 编辑: 更新查询以仅使用一个呼叫。

  • 问题内容: 我有两个表: 这是我的查询: 并为此: 它在第一个表上使用的全索引扫描进行排序,但不使用y索引进行连接(在解释中)。这对性能非常不利,并且会杀死整个数据库服务器,因为这是一个非常频繁的查询。 我尝试使用反转表顺序,但这给了,甚至更糟。 有什么办法可以使mysql同时使用索引进行连接和排序? ===更新=== 我真的很绝望。也许某种形式的非规范化可以在这里有所帮助? 问题答案: 如果您有

  • 我有一个AWS DynamoDb表, 我有user_id作为索引或GSI(user_id-index), 还有product_type作为索引或GSI(prod_type-index). 我试图使用KeyConditionExpression来查询DynamoDb表, 但是我得到了一个- 引用- Dynamodb查询错误-不支持查询键条件 https://docs.aws.amazon.com/a

  • 问题内容: 当我尝试使用此查询时,我收到一条错误消息,指出Perameter电子邮件不存在,我确定变量:email,login_pass,payment_method,operateur是有效的并且存在。 我尝试删除引号,但我得到了 您的Sql语法有错误,请在第1行的’:email,:login_pass,:payment_method,:avecpuce)’附近查看与您的SQL Server对应