0

I am trying to authenticate to my Google analytics account using a the service account p12 file. The code below should be authenticating to my analytics account and requesting the data that I need however I am getting an error with the X509Certificate2 when I run the code below. I have put my p12 file in bin/debug folder of my project with given credentials.

var certificate = new X509Certificate2(keyFilePath, keyPassword, X509KeyStorageFlags.Exportable);

I am getting the following Error:

An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Google.Apis.Analytics.v3;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;

namespace GoogleAnalytics
{
    public partial class MainForm : Form
    {
        private string keyFilePath = @"CSharpApplication-9f9f7643f6.p12";
        private string serviceAccountEmail = "56849870-9pqlki56dvp3bn64nais8ndes@developer.gserviceaccount.com";
        private string keyPassword = "notasecret";
        private string websiteCode = "67881935";
        private AnalyticsService service = null;
        private List<ChartRecord> visitsData = new List<ChartRecord>();

        public MainForm()
        {
            InitializeComponent();
        }

        private void Authenticate()
        {
            //loading the Key file
            var certificate = new X509Certificate2(keyFilePath, keyPassword, X509KeyStorageFlags.Exportable);

            var scopes =
          new string[] {
             AnalyticsService.Scope.Analytics,              // view and manage your analytics data
             AnalyticsService.Scope.AnalyticsEdit,          // edit management actives
             AnalyticsService.Scope.AnalyticsManageUsers,   // manage users
             AnalyticsService.Scope.AnalyticsReadonly};     // View analytics data       

            var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
            {
                Scopes = scopes
            }.FromCertificate(certificate));

            service = new AnalyticsService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential
            });
        }

        private void QueryData()
        {
            DataResource.GaResource.GetRequest request = service.Data.Ga.Get(
               "ga:" + websiteCode,
               DateTime.Today.AddDays(-15).ToString("yyyy-MM-dd"),
               DateTime.Today.ToString("yyyy-MM-dd"),
               "ga:sessions");
            request.Dimensions = "ga:year,ga:month,ga:day";
            var data = request.Execute();

            foreach (var row in data.Rows)
            {
                visitsData.Add(new ChartRecord(new DateTime(int.Parse(row[0]), int.Parse(row[1]), int.Parse(row[2])).ToString("MM-dd-yyyy"), int.Parse(row[3])));
            }
        }

        private void PopulateChart()
        {
            analyticsChart.Series[0].XValueMember = "Date";
            analyticsChart.Series[0].YValueMembers = "Visits";
            analyticsChart.DataSource = visitsData;
            analyticsChart.DataBind();
        }

        private void btnData_Click(object sender, EventArgs e)
        {
            Authenticate();
            QueryData();
            PopulateChart();
        }
    }
}

UPDATE: With below answered code i get errors like

'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities\14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities.Sync\14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Debugger.Runtime\14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Debugger.Runtime.dll'. 
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\GoogleAnalytics2.vshost.exe'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml.Linq\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.Linq.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Data.DataSetExtensions\v4.0_4.0.0.0__b77a5c561934e089\System.Data.DataSetExtensions.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.CSharp\v4.0_4.0.0.0__b03f5f7f11d50a3a\Microsoft.CSharp.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Net.Http\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Net.Http.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll'. Cannot find or open the PDB file.
The thread 0x3714 has exited with code 0 (0x0).
The thread 0x398c has exited with code 0 (0x0).
The thread 0x289c has exited with code 0 (0x0).
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\GoogleAnalytics2.exe'. Symbols loaded.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\Google.Apis.AnalyticsReporting.v4.dll'. Symbols loaded.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\Google.Apis.dll'. Symbols loaded.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\Google.Apis.Core.dll'. Symbols loaded.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\Google.Apis.Auth.PlatformServices.dll'. Symbols loaded.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\Google.Apis.Auth.dll'. Symbols loaded.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'. Cannot find or open the PDB file.
'GoogleAnalytics2.vshost.exe' (CLR v4.0.30319: GoogleAnalytics2.vshost.exe): Loaded 'c:\users\star\documents\visual studio 2015\Projects\GoogleAnalytics2\GoogleAnalytics2\bin\Release\Newtonsoft.Json.dll'. Cannot find or open the PDB file.
The thread 0x1228 has exited with code 0 (0x0).
The thread 0x30cc has exited with code 0 (0x0).
The program '[10788] GoogleAnalytics2.vshost.exe' has exited with code 0 (0x0).
The program '[10788] GoogleAnalytics2.vshost.exe: Program Trace' has exited with code 0 (0x0).

where my program.cs file is

namespace GoogleAnalytics2
{
    class Program
    {
        static void Main(string[] args)
        {
           System.Console.WriteLine(ServiceAccountAuthExample.AuthenticateServiceAccount("analyticsdemo@ultimate-triode-151909.iam.gserviceaccount.com", "C:/Users/star/Downloads/CSharpApplication-9f9f557643f6.p12"));
        }
    }
}

Plese help on this.What i am missing here. Any help is appreciated.

daisy
  • 357
  • 3
  • 7
  • 22
  • try tweeking your code a little , X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); If that doesn't work I have some code that uses the Json file for service accounts instead of the p12 file if you like. – Linda Lawton - DaImTo Dec 08 '16 at 08:29
  • The exception comes with a message, please post that message. – Lasse V. Karlsen Dec 08 '16 at 08:31
  • Side note: This is a service account really you only need to request the one scope AnalyticsService.Scope.Analytics asking for the others is kind of over kill. – Linda Lawton - DaImTo Dec 08 '16 at 08:37
  • @DaImTo Its showing me same error. Even after changing it to new X509Certificate2(keyFilePath, keyPassword, X509KeyStorageFlags.MachineKeySet). For keyfilepath should i give whole path? – daisy Dec 08 '16 at 10:02
  • I normally supply the full path to the key file yes. – Linda Lawton - DaImTo Dec 08 '16 at 10:15

1 Answers1

0

I have seen issues with the P12 file in the past. I have yet to be able to fully diagnose the problem. Sometimes its just easer to down load the service account .json file instead. Google is calling p12 backwards compatible anyway so they may eventually stop using p12 files.

This is the method I use for authenticating a service account. It will figure out itself what type of credentials file you are sending it.

    /// <summary>
    /// Authenticating to Google using a Service account
    /// Documentation: https://developers.google.com/accounts/docs/OAuth2#serviceaccount
    /// </summary>
    /// <param name="serviceAccountEmail">From Google Developer console https://console.developers.google.com</param>
    /// <param name="serviceAccountCredentialFilePath">Location of the .p12 or Json Service account key file downloaded from Google Developer console https://console.developers.google.com</param>
    /// <returns>AnalyticsService used to make requests against the Analytics API</returns>
    public static AnalyticsService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath)
    {
        try
        {
            if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
                throw new Exception("Path to the service account credentials file is required.");
            if (!File.Exists(serviceAccountCredentialFilePath))
                throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
            if (string.IsNullOrEmpty(serviceAccountEmail))
                throw new Exception("ServiceAccountEmail is required.");

            // These are the scopes of permissions you need. It is best to request only what you need and not all of them
            string[] scopes = new string[] { AnalyticsReportingService.Scope.Analytics };             // View your Google Analytics data

            // For Json file
            if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
            {
                GoogleCredential credential;
                using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
                {
                    credential = GoogleCredential.FromStream(stream)
                         .CreateScoped(scopes);
                }

                // Create the  Analytics service.
                return new AnalyticsService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Analytics Authentication Sample",
                });
            }
            else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
            {   // If its a P12 file

                var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
                {
                    Scopes = scopes
                }.FromCertificate(certificate));

                // Create the  Analytics service.
                return new AnalyticsService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Analytics Authentication Sample",
                });

            }
            else
            {
                throw new Exception("Unsupported Service accounts credentials.");
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("Create service account AnalyticsService failed" + ex.Message);
            throw new Exception("CreateServiceAccountAnalyticsServiceFailed", ex);
        }
    }

Code ripped from my tutorial Google Service accounts with Json file

Usage:

var service = AnalyticsService AuthenticateServiceAccount(.....);
DataResource.GaResource.GetRequest request = service.Data.Ga.Get(
               "ga:" + websiteCode,
               DateTime.Today.AddDays(-15).ToString("yyyy-MM-dd"),
               DateTime.Today.ToString("yyyy-MM-dd"),
               "ga:sessions");
            request.Dimensions = "ga:year,ga:month,ga:day";
            var data = request.Execute();

            foreach (var row in data.Rows)
            {
                visitsData.Add(new ChartRecord(new DateTime(int.Parse(row[0]), int.Parse(row[1]), int.Parse(row[2])).ToString("MM-dd-yyyy"), int.Parse(row[3])));
            }
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • I created console application and updated code as soon in query. While in run mode i get like above. those are not erors.What should i do for this? – daisy Dec 08 '16 at 11:52
  • did you add the Nuget package? Is your project set to .net 4.5 or greater? http://stackoverflow.com/questions/15937707/error-message-cannot-find-or-open-the-pdb-file – Linda Lawton - DaImTo Dec 08 '16 at 12:24
  • I think your code is just finding p12 file and getting datas from it. i wont see any variable where it can show analytical data stats. How could i get datas like pageviews, traffic. – daisy Dec 08 '16 at 12:35
  • the code returns a valid AnalyticsService which is exactly the same as your "service". I updated the code to Analytics v3 for you. I thought you were using Analytics v4. If you send my method a p12 file then yes it will read from the credentials from a p12 file. If you send it the .json file then it will read the credentials from a .json credentials file both will create you a AnalyticsService – Linda Lawton - DaImTo Dec 08 '16 at 12:36
  • Then i think i am not printing it correcting, Can you look into Program.cs file shown in my question. That is how i am printing data by calling your class method. and i have used console project. Can you have a look into it. – daisy Dec 08 '16 at 12:40
  • Call the AuthenticateServiceAccount get the service use the service in your call to ga.get() You have the code for ga.get already. This tutorial might help you as well http://www.daimto.com/googleanalytics-core-csharp/ – Linda Lawton - DaImTo Dec 08 '16 at 12:43