.NET Google GData Docs API 与 OAuth 2.0 返回 401

发布于 2024-12-09 12:35:10 字数 2833 浏览 1 评论 0原文

我目前正在编写一个使用 Google 文档和日历 API 的 .NET WPF 应用程序。我计划在稍后阶段集成一些较新的 API,例如任务,因此我想现在就开始使用 OAuth 2.0。我已经能够获取并存储刷新和访问令牌,并且我已经实现了一些逻辑,以便在当前令牌过期时检索更多访问令牌。但是,我在将文档上传到谷歌文档时遇到很多麻烦。看来 GData 客户端库本身并不支持 OAuth 2.0,而且我不想迁移到较新的客户端库(例如任务),因为我不希望在现阶段依赖于 DotNetOpenAuth。相反,我实现了自己的 OAuth2Authenticator,它添加了所需的 OAuth 2 标头,并且我将其与 GData ResumableUploader 一起使用。当我尝试使用 ResumableUploader 发送上传文档的请求时,我收到 401 Unauthorized 响应,其中包含消息“令牌无效 - 无效的 AuthSub 令牌”。

我正在拨打这样的电话:

ResumableUploader ru = new ResumableUploader(512);

Document entry = new Document();
entry.Title = documentName;
entry.MediaSource = new MediaFileSource(localDocumentPath, "application/pdf");
entry.Type = Document.DocumentType.PDF;

Uri createUploadUrl = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full");
AtomLink link = new AtomLink(createUploadUrl.AbsoluteUri);
link.Rel = ResumableUploader.CreateMediaRelation;
entry.DocumentEntry.Links.Add(link);

ru.Insert(new OAuth2Authenticator("MyApplicationName", "MyAccessToken"), entry.DocumentEntry);

导致此请求(来自 Fiddler):

POST https://docs.google.com/feeds/upload/create-session/default/private/full
HTTP/1.1 Authorization: OAuth sOmeTThing+SomThNig+etc==
Slug: DOC_0108.pdf
X-Upload-Content-Type: application/pdf
X-Upload-Content-Length: 175268
GData-Version: 3.0
Host: docs.google.com
Content-Type: application/atom+xml; charset=UTF-8
Content-Length: 508 Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
 xmlns:gd="http://schemas.google.com/g/2005"
 xmlns:docs="http://schemas.google.com/docs/2007">
   <title type="text">DOC_0108.pdf</title>
   <link href="https://docs.google.com/feeds/upload/create-session/default/private/full"
    rel="http://schemas.google.com/g/2005#resumable-create-media" />  
   <category term="http://schemas.google.com/docs/2007#pdf"
    scheme="http://schemas.google.com/g/2005#kind" label="pdf" />
</entry>

以及关联的 401 响应:

HTTP/1.1 401 Unauthorized
Server: HTTP Upload Server Built on Sep 27 2011 04:44:57 (1317123897)
WWW-Authenticate: AuthSub realm="http://www.google.com/accounts/AuthSubRequest"
Content-Type: text/html; charset=UTF-8
Content-Length: 38
Date: Thu, 13 Oct 2011 08:45:11 GMT
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate

Token invalid - Invalid AuthSub token.

我已经尝试了“授权:OAuth”和“标题中的 Authorization: Bearer' ,因为 API 和 OAuth 2.0 文档似乎是分开的,而且我还尝试将令牌附加为查询字符串(?access_token= 和 ?oauth_token=)但所有这些事情都会给出相同的反应。

我已经浏览了所有我能找到的 Google API 和 OAuth 问题、博客文章、文档,并尝试了多种执行此调用的方法(.NET GData API 的多种实现、REST 客户端 NuGet 包、我自己的 REST 客户端实现,等等),我无法解决这个问题。

任何帮助将不胜感激。

I'm currently writing a .NET WPF application that uses the Google Docs and Calendar APIs. I'm planning to integrate some of the newer APIs, like Tasks, at a later stage so I want to start using OAuth 2.0 now in preparation. I've been able to obtain and store both a refresh and access token and I've implemented some logic to retrieve further access tokens when the current ones expire. However I'm having a lot of trouble uploading a document to google docs. It seems that the GData client libraries don't natively support OAuth 2.0 and I don't want to move to the newer client libraries (e.g. for Tasks) because I don't want a dependency on DotNetOpenAuth at this stage. Instead I've implemented my own OAuth2Authenticator which adds the required OAuth 2 header and I'm using this with the GData ResumableUploader. When I try to send the request to upload a document with the ResumableUploader I get a 401 Unauthorised response with the message Token Invalid - Invalid AuthSub token.

I'm making the call like this:

ResumableUploader ru = new ResumableUploader(512);

Document entry = new Document();
entry.Title = documentName;
entry.MediaSource = new MediaFileSource(localDocumentPath, "application/pdf");
entry.Type = Document.DocumentType.PDF;

Uri createUploadUrl = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full");
AtomLink link = new AtomLink(createUploadUrl.AbsoluteUri);
link.Rel = ResumableUploader.CreateMediaRelation;
entry.DocumentEntry.Links.Add(link);

ru.Insert(new OAuth2Authenticator("MyApplicationName", "MyAccessToken"), entry.DocumentEntry);

Which results in this request (from Fiddler):

POST https://docs.google.com/feeds/upload/create-session/default/private/full
HTTP/1.1 Authorization: OAuth sOmeTThing+SomThNig+etc==
Slug: DOC_0108.pdf
X-Upload-Content-Type: application/pdf
X-Upload-Content-Length: 175268
GData-Version: 3.0
Host: docs.google.com
Content-Type: application/atom+xml; charset=UTF-8
Content-Length: 508 Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
 xmlns:gd="http://schemas.google.com/g/2005"
 xmlns:docs="http://schemas.google.com/docs/2007">
   <title type="text">DOC_0108.pdf</title>
   <link href="https://docs.google.com/feeds/upload/create-session/default/private/full"
    rel="http://schemas.google.com/g/2005#resumable-create-media" />  
   <category term="http://schemas.google.com/docs/2007#pdf"
    scheme="http://schemas.google.com/g/2005#kind" label="pdf" />
</entry>

And associated 401 response:

HTTP/1.1 401 Unauthorized
Server: HTTP Upload Server Built on Sep 27 2011 04:44:57 (1317123897)
WWW-Authenticate: AuthSub realm="http://www.google.com/accounts/AuthSubRequest"
Content-Type: text/html; charset=UTF-8
Content-Length: 38
Date: Thu, 13 Oct 2011 08:45:11 GMT
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate

Token invalid - Invalid AuthSub token.

I've tried both 'Authorization: OAuth' and 'Authorization: Bearer' in the headers, as the API and OAuth 2.0 documentation seems divided, and I've also tried appending the token as a query string (?access_token= and ?oauth_token=) but all of those things give the same response.

I've been through all the Google API and OAuth questions, blog posts, documentation I can find and tried numerous ways of performing this call (multiple implementations with the .NET GData APIs, a REST client NuGet package, my own REST client implementation, etc.) and I can't get past this issue.

Any help will be most appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜点 2024-12-16 12:35:10

我能够使用 OAuth 获取和创建文档。一旦我通过 Google 身份验证以访问文档范围,我就会执行以下操作:

// get the list of available google docs
        RequestSettings settings = new RequestSettings(kApplicationName);
        settings.AutoPaging = false;
        if (settings != null)
        {
            DocumentsRequest request = new DocumentsRequest(settings);
            request.Service.RequestFactory = GetGoogleOAuthFactory();
            Feed<Document> feed = request.GetEverything();

            List<Document> all = new List<Document>(feed.Entries);

            // loop through the documents and add them from google
            foreach (Document entry in all)
            {
                // first check to see whether the document has already been selected or not
                bool found = model.Docs.Any(d => d.GoogleDocID == entry.ResourceId);
                if (!found)
                {
                    GoogleDocItem doc = new GoogleDocItem();
                    doc.GoogleDocID = entry.ResourceId;
                    doc.ETag = entry.ETag;

                    doc.Url = entry.DocumentEntry.AlternateUri.Content;
                    doc.Title = entry.Title;
                    doc.DocType = entry.Type.ToString();
                    doc.DocTypeID = entry.Type;

                    if (entry.ParentFolders.Count == 0)
                    {
                        // add the doc to the list
                        model.AvailableDocs.Add(doc);

                        // if the doc is a folder, get the children
                        if (doc.DocTypeID == Document.DocumentType.Folder)
                        {
                            AddAllChildrenToFolder(ref doc, entry, all);
                        }
                    }
                }
            }
        }

public GOAuthRequestFactory GetGoogleOAuthFactory()
    {
        // build the base parameters
        OAuthParameters parameters = new OAuthParameters
        {
            ConsumerKey = kConsumerKey,
            ConsumerSecret = kConsumerSecret
        };

        // check to see if we have saved tokens and set
        var tokens = (from a in context.GO_GoogleAuthorizeTokens select a);
        if (tokens.Count() > 0)
        {
            GO_GoogleAuthorizeToken token = tokens.First();
            parameters.Token = token.Token;
            parameters.TokenSecret = token.TokenSecret;
        }

        // now build the factory
        return new GOAuthRequestFactory("anyname", kApplicationName, parameters);
    }

我在此处发布了我的授权示例:.net - Google / OAuth 2 - 自动登录。 DocumentsRequest 来自 Google 的 .NET 二进制文件。虽然我还没有用它创建新文档,但我确实使用类似的类来创建日历项目。

I am able to get and create documents with OAuth. Once I've authenticated with Google to have access to the docs scope, I do the following:

// get the list of available google docs
        RequestSettings settings = new RequestSettings(kApplicationName);
        settings.AutoPaging = false;
        if (settings != null)
        {
            DocumentsRequest request = new DocumentsRequest(settings);
            request.Service.RequestFactory = GetGoogleOAuthFactory();
            Feed<Document> feed = request.GetEverything();

            List<Document> all = new List<Document>(feed.Entries);

            // loop through the documents and add them from google
            foreach (Document entry in all)
            {
                // first check to see whether the document has already been selected or not
                bool found = model.Docs.Any(d => d.GoogleDocID == entry.ResourceId);
                if (!found)
                {
                    GoogleDocItem doc = new GoogleDocItem();
                    doc.GoogleDocID = entry.ResourceId;
                    doc.ETag = entry.ETag;

                    doc.Url = entry.DocumentEntry.AlternateUri.Content;
                    doc.Title = entry.Title;
                    doc.DocType = entry.Type.ToString();
                    doc.DocTypeID = entry.Type;

                    if (entry.ParentFolders.Count == 0)
                    {
                        // add the doc to the list
                        model.AvailableDocs.Add(doc);

                        // if the doc is a folder, get the children
                        if (doc.DocTypeID == Document.DocumentType.Folder)
                        {
                            AddAllChildrenToFolder(ref doc, entry, all);
                        }
                    }
                }
            }
        }

public GOAuthRequestFactory GetGoogleOAuthFactory()
    {
        // build the base parameters
        OAuthParameters parameters = new OAuthParameters
        {
            ConsumerKey = kConsumerKey,
            ConsumerSecret = kConsumerSecret
        };

        // check to see if we have saved tokens and set
        var tokens = (from a in context.GO_GoogleAuthorizeTokens select a);
        if (tokens.Count() > 0)
        {
            GO_GoogleAuthorizeToken token = tokens.First();
            parameters.Token = token.Token;
            parameters.TokenSecret = token.TokenSecret;
        }

        // now build the factory
        return new GOAuthRequestFactory("anyname", kApplicationName, parameters);
    }

I posted my authorization sample over here: .net - Google / OAuth 2 - Automatic logon. The DocumentsRequest is from the .NET binaries from Google. While I haven't created a new document with this yet, I do use similar classes to create Calendar items.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文