tienes - Cómo iniciar sesión en Google API con la cuenta de servicio en C#- Credenciales no válidas
integrar login google en mi web (3)
Me estoy golpeando a mí mismo al tratar de obtener un inicio de sesión de cuenta de servicio simple para trabajar en C #, en la API de Google y en Google Analytics. Mi empresa ya está obteniendo datos en Analytics, y puedo consultar información con su Explorador de consultas, pero el inicio en .Net no va a ninguna parte. Estoy usando un archivo json generado por Google con PKI, ya que la documentación dice que dicha cuenta de servicio es la forma correcta de comunicación de computadora a computadora con la API de Googla. Código snipet:
public static GoogleCredential _cred;
public static string _exePath;
static void Main(string[] args) {
_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(@"file:/", "");
var t = Task.Run(() => Run());
t.Wait();
}
private static async Task Run() {
try {
// Get active credential
using (var stream = new FileStream(_exePath + "//Default-GASvcAcct-508d097b0bff.json", FileMode.Open, FileAccess.Read)) {
_cred = GoogleCredential.FromStream(stream);
}
if (_cred.IsCreateScopedRequired) {
_cred.CreateScoped(new string[] { AnalyticsService.Scope.Analytics });
}
// Create the service
AnalyticsService service = new AnalyticsService(
new BaseClientService.Initializer() {
HttpClientInitializer = _cred,
});
var act1 = service.Management.Accounts.List().Execute(); // blows-up here
Todo se compila bien, pero cuando llega a la sentencia Execute (), se GoogleApiException
un error GoogleApiException
:
Ubicación de [Credenciales no válidas] [Autorización - encabezado] Motivo [authError] Dominio [global]
¿Qué me estoy perdiendo?
Otra opción es usar GoogleCredential.GetApplicationDefault()
. Creo que este es el enfoque recomendado actualmente (octubre de 2018). Aquí hay algunos F #, pero es más o menos lo mismo en la sintaxis de módulo de C #:
let projectId = "<your Google Cloud project ID...>"
let creds =
GoogleCredential.GetApplicationDefault()
.CreateScoped(["https://www.googleapis.com/auth/cloud-platform"])
use service =
new CloudBuildService(
BaseClientService.Initializer(HttpClientInitializer=creds))
let foo = service.Projects.Builds.List(projectId).Execute()
Ahora, solo asegúrese de que configura GOOGLE_APPLICATION_CREDENTIALS
para que apunte al archivo con el archivo JSON de credenciales, por ejemplo. GOOGLE_APPLICATION_CREDENTIALS=creds.json dotnet run
.
Parece que los GoogleAnalytics no pueden consumir un GoogleCredential
genérico e interpretarlo como un ServiceAccountCredential
(aunque se reconozca, de forma interina, que en realidad es de ese tipo ). Por lo tanto, tienes que crear un ServiceAccountCredential
la manera más difícil. También es lamentable que GoogleCredential
no exponga las diversas propiedades de la credencial, por lo que tuve que crear la mía.
Utilicé el generador de clases JSON C # en http://jsonclassgenerator.codeplex.com/ para crear un objeto "personal" ServiceAccountCredential utilizando la biblioteca JSON que es una parte automática de la API de Google (Newtonsoft.Json), recuperé partes esenciales de las descargas. Archivo json de la cuenta de servicio, para construir la credencial requerida, utilizando sus propiedades de correo electrónico y clave privada. Al pasar un ServiceAccountCredential
genuino al constructor del servicio GoogleAnalytics, se obtiene un inicio de sesión exitoso y el acceso a los recursos permitidos de esa cuenta.
Muestra de código de trabajo a continuación:
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Analytics.v3;
using Newtonsoft.Json;
.
.
.
try
{
// Get active credential
string credPath = _exePath + @"/Private-67917519b23f.json";
var json = File.ReadAllText(credPath);
var cr = JsonConvert.DeserializeObject<PersonalServiceAccountCred>(json); // "personal" service account credential
// Create an explicit ServiceAccountCredential credential
var xCred = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(cr.ClientEmail)
{
Scopes = new[] {
AnalyticsService.Scope.AnalyticsManageUsersReadonly,
AnalyticsService.Scope.AnalyticsReadonly
}
}.FromPrivateKey(cr.PrivateKey));
// Create the service
AnalyticsService service = new AnalyticsService(
new BaseClientService.Initializer()
{
HttpClientInitializer = xCred,
}
);
// some calls to Google API
var act1 = service.Management.Accounts.List().Execute();
var actSum = service.Management.AccountSummaries.List().Execute();
var resp1 = service.Management.Profiles.List(actSum.Items[0].Id, actSum.Items[0].WebProperties[0].Id).Execute();
Algunos pueden preguntarse cómo se ve una credencial de cuenta de servicio generada por Google con PKI (clave privada). Desde el Administrador de API de Google (IAM & Admin) en https://console.developers.google.com/iam-admin/projects , seleccione el proyecto apropiado (tiene al menos uno de estos). Ahora seleccione Cuentas de servicio (de los enlaces de navegación a la izquierda) y CREAR CUENTA DE SERVICIO en la parte superior de la pantalla. Ingrese un nombre, configure la casilla de verificación Proporcionar una nueva clave privada , luego haga clic en Crear . Google provocará una descarga automática de un archivo JSON, que se parece a esto:
{
"type": "service_account",
"project_id": "atomic-acrobat-135",
"private_key_id": "508d097b0bff9e90b8d545f984888b0ef31",
"private_key": "-----BEGIN PRIVATE KEY-----/nMIIE...o/0=/n-----END PRIVATE KEY-----/n",
"client_email": "[email protected]",
"client_id": "1123573016559832",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-analytics%40atomic-acrobat-135923.iam.gserviceaccount.com"
}
Se está produciendo el error de credenciales no válidas porque los ámbitos que especificó no se envían con sus credenciales. CreateScoped
el mismo error y solo me di cuenta después de la depuración y aún vi 0 ámbitos en la credencial después de la llamada a CreateScoped
.
Un GoogleCredential
es inmutable, por lo que CreateScoped
crea una nueva instancia con el conjunto de ámbitos especificados.
Reasigne su variable de credenciales con el resultado de ámbito como tal y debería funcionar:
if (_cred.IsCreateScopedRequired) {
_cred = _cred.CreateScoped(AnalyticsService.Scope.Analytics);
}
La respuesta aceptada funciona porque está logrando lo mismo de una manera más difícil.