Как установить return_uri для GoogleWebAuthorizationBroker.AuthorizeAsync?
Я пытаюсь использовать API календаря Google в своем веб-приложении, отличном от MVC.NET. (Это, по-видимому, важное различие.)
Я попытался использовать код из этого примера в Google и этот пример в Daimto вместе с некоторыми полезными подсказками из нескольких связанных постов здесь.
Я написал следующий метод:
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
}
Проблема в том, что, когда вызывается страница OAuth2 от Google, redirect_uri
продолжает устанавливаться в http://localhost:<some-random-port>/authorize
. Я не знаю, как установить это на что-то еще, как в следующем примере URL, созданного AuthorizeAsync
:
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 перенаправления в запросе: http://localhost: XXXXX/authorize/ не соответствует зарегистрированному URI переадресации"
Я могу зарегистрировать столько URL-адресов Redirect на странице "Учетные данные консоли разработчика Google". Я не склонен регистрировать порты 65535, и я хочу использовать страницу, отличную от /authorize
на моем сайте. В частности, я хочу использовать во время разработки http://localhost:888/Pages/GoogleApiRedirect
но не имею в http://localhost:888/Pages/GoogleApiRedirect
, где бы я это установил, помимо того, что я сделал в консоли разработчика.
Как явным образом задаю значение redirect_uri
? Я также открыт для ответа в форме "Этот подход совершенно неверен".
РЕДАКТИРОВАТЬ:
После игры с этим в прошлый день я обнаружил, что с помощью Client ID/Client Secret для собственного приложения, а не веб-приложения, я могу по крайней мере перейти на страницу авторизации веб-сайта Google, не жалуясь на redirect_uri_mismatch. Это все еще неприемлемо, потому что он по-прежнему возвращается к http://localhost:<some-random-port>/authorize
, который находится вне контроля моего веб-приложения.
Ответы
Ответ 1
Вы можете использовать этот код: (оригинальная идея от http://coderissues.com/info/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);
}
}
}