10

Google has recently started to give us a Json key file for service account instead of the P12 key file. I have been trying to get this there isn't a lot of information out there and what info I have seen says this should work.

string[] scopes = new string[] { DriveService.Scope.Drive}; 

Stream stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
var credential = GoogleCredential.FromStream(stream).CreateScoped(scopes); 

However its throwing the following exception

Error creating credential from JSON. Unrecognized credential type .

I have double checked the json key file downloaded two different ones trying to get it to work nothing.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • As per @jon-skeet 's comment in https://stackoverflow.com/questions/75661327/c-sharp-get-credentials-from-google-sheets-api > try https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#installed-applications – Alex P. Jun 28 '23 at 07:51

4 Answers4

12

I think you are using file google-services.json downloaded from Firebase. This isn't file you need. Process you have to do is:

  1. Go to Firebase Console
  2. Click on Settings
  3. Click on Project Settings
  4. Click on Service accounts
  5. Click on Generate new private key button
  6. Use file generated by this method.
Kamil
  • 782
  • 1
  • 9
  • 24
2

I downloaded a Service Account json key file and tried the same code and it works fine. I was able to replicate the issue if I manually corrupted the "type" field in the json key file. Can you re-download a json key file and try again. Here is what the json key file should look like (sensitive data removed):

{
  "type": "service_account",
  "project_id": ...,
  "private_key_id": ...,
  "private_key": ...,
  "client_email": ...,
  "client_id": ...,
  "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": ...
}
0

The following code is used for authentication with either the old json file or the .p12 file.

public static class ServiceAccountExample
    {

        /// <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 CalendarService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
        {
            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.");                

                // 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 CalendarService(new BaseClientService.Initializer()
                    {
                        HttpClientInitializer = credential,
                        ApplicationName = "Calendar Service account 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  Calendar service.
                    return new CalendarService(new BaseClientService.Initializer()
                    {
                        HttpClientInitializer = credential,
                        ApplicationName = "Calendar Authentication Sample",
                    });
                }
                else
                {
                    throw new Exception("Unsupported Service accounts credentials.");
                }

            }
            catch (Exception ex)
            {                
                throw new Exception("CreateServiceAccountCalendarFailed", ex);
            }
        }
    }
}

Code ripped from ServiceAccount.cs

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
-1

I think that you first need to deserialize the stream, at least that what I found at: https://github.com/google/google-api-dotnet-client/blob/a5288c4493a12791b46f7142efacb83c4fcacf58/Src/Support/GoogleApis.Auth.PlatformServices_Shared/OAuth2/DefaultCredentialProvider.cs#L169

Try it out and let us know. And yes, we need to improve the documentation, but let's first find the problem and then I'll open a new issue in GitHub with the specific request.

peleyal
  • 3,472
  • 1
  • 14
  • 25
  • The file is available now here: https://github.com/google/google-api-dotnet-client/blob/a5288c4493a12791b46f7142efacb83c4fcacf58/Src/Support/GoogleApis.Auth.PlatformServices_Shared/OAuth2/DefaultCredentialProvider.cs. I updated my comment with the right link – peleyal Dec 04 '16 at 19:23