Kred
Kred

Reputation: 339

How to use Admob API on c# via Service Account?

I'd like to use Admob API on a server-to-server app made with .net via Service Account to avoid manual login to require the token. After creating the certification, I wrote this dependency:

public AdMobService RegisterAdMobService(IServiceFactory factory)
        {
            var settings = factory.GetInstance<IOptions<SettingsModel>>().Value.AdMob;
            var certificate = new X509Certificate2(settings.CertificateFileName, settings.Password, X509KeyStorageFlags.Exportable);

            ServiceAccountCredential credential = new ServiceAccountCredential(
               new ServiceAccountCredential.Initializer(settings.ServiceEmail)
               {
                   Scopes = new[] { settings.Scope } // https://www.googleapis.com/auth/admob.report
               }.FromCertificate(certificate));


            return new AdMobService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "App"
            });
        }

But it return this error:

'dotnet.exe' (CoreCLR: clrhost): loading 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\1.1.2\System.IO.UnmanagedMemoryStream.dll' completed. 
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware:Error: An unhandled exception has occurred: [{
  "error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "errors": [
      {
        "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
        "domain": "global",
        "reason": "unauthorized"
      }
    ],
    "status": "UNAUTHENTICATED"
  }
}
]

The service admob has thrown an exception: Google.GoogleApiException: [{
  "error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "errors": [
      {
        "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
        "domain": "global",
        "reason": "unauthorized"
      }
    ],
    "status": "UNAUTHENTICATED"
  }
}
] ---> Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Google.Apis.Util.StandardResponse`1[System.Object]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Google.Apis.Json.NewtonsoftJsonSerializer.Deserialize[T](String input) in C:\Apiary\2020-06-01.14-07-07\Src\Support\Google.Apis.Core\Json\NewtonsoftJsonSerializer.cs:line 188
   at Google.Apis.Services.BaseClientService.<DeserializeError>d__37.MoveNext() in C:\Apiary\2020-06-01.14-07-07\Src\Support\Google.Apis\Services\BaseClientService.cs:line 333
   --- End of inner exception stack trace ---
   at Google.Apis.Services.BaseClientService.<DeserializeError>d__37.MoveNext() in C:\Apiary\2020-06-01.14-07-07\Src\Support\Google.Apis\Services\BaseClientService.cs:line 341
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Google.Apis.Requests.ClientServiceRequest`1.<ParseResponse>d__31.MoveNext() in C:\Apiary\2020-06-01.14-07-07\Src\Support\Google.Apis\Requests\ClientServiceRequest.cs:line 249
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Google.Apis.Requests.ClientServiceRequest`1.<ExecuteAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---

Is there a client for that where I could fetch a token, like this one

return new GooglePlayClient
            {
                TokenProvider = new TokenProvider(settings.ServiceEmail, settings.CertificateFileName, "https://www.googleapis.com/auth/androidpublisher")
            };

What am I missing?

Upvotes: 1

Views: 750

Answers (1)

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 116878

The admob api does not appear to support service account authentication.

Your application must use OAuth 2.0 to authorize requests. No other authorization protocols are supported. If your application uses Google Sign-In, some aspects of authorization are handled for you.

Upvotes: 2

Related Questions