asp.net 如何为GoogleWebAuthorizationBroker.AuthorizeAsync设置return_uri?

j2qf4p5b  于 2022-11-19  发布在  .NET
关注(0)|答案(4)|浏览(123)

我尝试在我的非MVC.NET Web应用程序中使用Google Calendar API。(这似乎是一个重要的区别。)
我试着使用Google的this example和Daimto的this example的代码沿着一些related posts here的有用提示。
我写了下面的方法:

public void GetUserCredential( String userName )
{
    String clientId = ConfigurationManager.AppSettings[ "Google.ClientId" ];            //From Google Developer console https://console.developers.google.com
    String clientSecret = ConfigurationManager.AppSettings[ "Google.ClientSecret" ];    //From Google Developer console https://console.developers.google.com
    String[] scopes = new string[] {
            Google.Apis.Calendar.v3.CalendarService.Scope.Calendar          
    };

    // here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
    UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync( new ClientSecrets
    {
        ClientId = clientId,
        ClientSecret = clientSecret             
    }, scopes, userName, CancellationToken.None, new FileDataStore( "c:\\temp" ) ).Result;

    // TODO: Replace FileDataStore with DatabaseDataStore
}

问题是,当调用Google的OAuth2页面时,redirect_uri一直被设置为http://localhost:<some-random-port>/authorize。我不知道如何将其设置为其他值,如下面的AuthorizeAsync生成的URL示例所示:

https://accounts.google.com/o/oauth2/auth?access_type=offline
    &response_type=code
    &client_id=********.apps.googleusercontent.com
    &redirect_uri=http:%2F%2Flocalhost:40839%2Fauthorize%2F
    &scope=https:%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar

Google以redirect_uri_mismatch错误页面响应,并显示以下消息:
“请求中的重定向URI:与已注册的重定向URI不匹配”
我只能在我的Google开发者控制台证书页面注册这么多的重定向URI。我不想注册65535个端口,我想在我的网站上使用一个不同于/authorize的页面。具体来说,我想在开发过程中使用http://localhost:888/Pages/GoogleApiRedirect,但除了我在开发者控制台中所做的之外,我不知道在哪里设置它。
我如何显式地设置redirect_uri的值?我也愿意接受“这种方法完全错误”的回答。

编辑:

在过去的一天里,我使用了这个方法,我发现通过使用Native Application的Client ID/Client Secret而不是Web Application,我至少可以访问Google的Web授权页面,而不会让它抱怨redirect_uri_mismatch。这仍然是不可接受的,因为它仍然会返回http://localhost:<some-random-port>/authorize,这不受Web Application的控制。

mlnl4t2r

mlnl4t2r1#

您可以使用以下代码:(原始想法来自http://coderissues.com/questions/27512300/how-to-append-login-hint-usergmail-com-to-googlewebauthorizationbroker

dsAuthorizationBroker.RedirectUri = "my localhost redirect uri";
UserCredential credential = await dsAuthorizationBroker.AuthorizeAsync(...

dsAuthorizationBroker.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Util.Store;

namespace OAuth2
{    
    public class dsAuthorizationBroker : GoogleWebAuthorizationBroker
    {
        public static string RedirectUri;

        public new static async Task<UserCredential> AuthorizeAsync(
            ClientSecrets clientSecrets,
            IEnumerable<string> scopes,
            string user,
            CancellationToken taskCancellationToken,
            IDataStore dataStore = null)
        {
            var initializer = new GoogleAuthorizationCodeFlow.Initializer
            {
                ClientSecrets = clientSecrets,
            };
            return await AuthorizeAsyncCore(initializer, scopes, user,
                taskCancellationToken, dataStore).ConfigureAwait(false);
        }

        private static async Task<UserCredential> AuthorizeAsyncCore(
            GoogleAuthorizationCodeFlow.Initializer initializer,
            IEnumerable<string> scopes,
            string user,
            CancellationToken taskCancellationToken,
            IDataStore dataStore)
        {
            initializer.Scopes = scopes;
            initializer.DataStore = dataStore ?? new FileDataStore(Folder);
            var flow = new dsAuthorizationCodeFlow(initializer);
            return await new AuthorizationCodeInstalledApp(flow, 
                new LocalServerCodeReceiver())
                .AuthorizeAsync(user, taskCancellationToken).ConfigureAwait(false);
        }
    }

    public class dsAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
    {
        public dsAuthorizationCodeFlow(Initializer initializer)
            : base(initializer) { }

        public override AuthorizationCodeRequestUrl
                       CreateAuthorizationCodeRequest(string redirectUri)
        {
            return base.CreateAuthorizationCodeRequest(dsAuthorizationBroker.RedirectUri);
        }
    }    
}
slwdgvem

slwdgvem2#

如果您尝试在.NET应用程序非Web服务器应用程序(即C#控制台应用程序命令行程序)中使用GoogleWebAuthorizationBroker.AuthorizeAsync,则在创建Google OAuth配置文件(https://console.developers.google.com/apis)时,在凭据中选择以下选项至关重要。

桌面应用程序-现在也称为已安装的应用程序

它隐藏在“帮助我选择”新凭据下。您必须创建一个显示桌面应用程序而不是WebApp的新凭据。

单击“帮助我选择”

选择您想要的API库

即(Google日历API、YouTube)选择“用户数据”

第3步- OAUTH客户端ID -桌面应用程序!

是-无需授权文件”

即Javascript &重定向现在您有一个没有Web应用程序重定向授权的配置文件

使用“下载JSON”并将其保存到应用程序中

参考。当你查看这个文件时,你会注意到一组不同的参数,告诉代理这是一个应用程序。在这个例子中,我正在访问日历API的范围。只需将范围更改为你试图访问的任何API。**

string[] Scopes = { CalendarService.Scope.Calendar }; //requires full scope to get ACL list..

string ApplicationName = "Name Of Your Application In Authorization Screen";
//just reference the namespaces in your using block
        
using (var stream = new FileStream("other_client_id.json", FileMode.Open, FileAccess.Read))
   {
   // The file token.json stores the user's access and refresh tokens, and is created
    // automatically when the authorization flow completes for the first time.
   string credPath = "other_token.json";
   credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
      GoogleClientSecrets.Load(stream).Secrets,
      Scopes,
      "user",
      CancellationToken.None,
      new FileDataStore(credPath, true)).Result;               
    }
        
// Create Google Calendar API service.
var service = new CalendarService(new BaseClientService.Initializer()
{
   HttpClientInitializer = credential,
   ApplicationName = ApplicationName,
});
        
//Then your ready to grab data from here using the methods mentioned in Google Calendar API docs

若要在Docker中执行此程式

当你把这个部署到Docker时,你会得到一个异常,即操作系统不支持运行该进程。基本上,它试图在Metal Box上打开一个浏览器。这在Docker中是不可能的。
要解决这个问题,请修改代码,使用完整的绝对路径,如下所示

var inputFolderAbsolute = Path.Combine(AppContext.BaseDirectory, "Auth.Store");
...
new FileDataStore(inputFolderAbsolute, true)
  • 在本地计算机上将此应用程序作为控制台应用程序运行,以便打开浏览器。
  • 选择要使用的帐户
  • 在bin文件夹中,将创建一个新文件夹和文件。
  • 将该文件夹复制到根路径
  • 设定要复制的档案(如果较新)
  • 部署到Dock
  • 由于已为您选择的帐户保存刷新令牌,因此它将获得新的访问令牌并工作。
  • 注意:刷新令牌可能由于任何原因过期。您必须重复上述步骤
ca1c2owp

ca1c2owp3#

在创建oAuth客户端ID时选择“其他”帮助我解决了重定向问题。(使用“Web应用程序”选项会尝试重定向到带有随机端口的URL,这非常烦人)
现在我的Gmail API工作起来就像一个魅力:)

qhhrdooz

qhhrdooz4#

如果你正在努力构建一个控制台应用程序,能够通过Gmail的身份验证来发送邮件,下面是一个有效的方法。LocalServerCodeReceiver是监听从浏览器返回的访问令牌的关键。如果需要,这个代码还将获得一个刷新令牌,并将在文件系统中缓存令牌以供将来使用。

var clientSecrets = new ClientSecrets
{
    ClientId = YOUR_CLIENTID,
    ClientSecret = YOUR_CLIENT_SECRET
};

var codeFlow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
    DataStore = new FileDataStore(AppDomain.CurrentDomain.BaseDirectory),
    Scopes = new[] { GmailService.Scope.MailGoogleCom },
    ClientSecrets = clientSecrets
});

var codeReceiver = new LocalServerCodeReceiver();
var authCode = new AuthorizationCodeInstalledApp(codeFlow, codeReceiver);
var credential = await authCode.AuthorizeAsync(EmailUser, CancellationToken.None);

if (authCode.ShouldRequestAuthorizationCode(credential.Token))
{
    await credential.RefreshTokenAsync(CancellationToken.None);
}

注意事项:

  • 根据我的经验,Firefox不能正确处理浏览器重定向,因此我必须将默认的Windows浏览器切换到Chrome浏览器才能使其正常工作
  • 尽管此代码是控制台应用程序的一部分,但它并没有完全设置为以无人值守的方式运行;除非令牌缓存在以前运行的文件系统上,否则您需要在浏览器弹出窗口中手动完成身份验证流程
  • 开发人员控制台中的OAuth客户端ID配置应设置为“Desktop”

相关问题