3

we are experiencing problems with API authentication of our project in asp-net core 3.1. Specifically we have integrated the text-to-speech service provided by Google. Locally everything works correctly, but this does not happen when the web-app is online.

try
        {

            var path = "C://GoogleVoice//food-safety-trainer-47a9337eda0f.json";

            var credential = GoogleCredential.FromFile(path);
            var storage = StorageClient.Create(credential);

            TextToSpeechClient client = TextToSpeechClient.Create();
            var test = client.GrpcClient;

            // The input can be provided as text or SSML.
            SynthesisInput input = new SynthesisInput
            {
                Text = text
            };

            VoiceSelectionParams voiceSelection = new VoiceSelectionParams();
            voiceSelection.LanguageCode = "it-IT";
            voiceSelection.Name = "it-IT-Wavenet-A";
            voiceSelection.SsmlGender = SsmlVoiceGender.Female;
            
            // The audio configuration determines the output format and speaking rate.
            AudioConfig audioConfig = new AudioConfig
            {
                AudioEncoding = AudioEncoding.Mp3
            };
            SynthesizeSpeechResponse response = client.SynthesizeSpeech(input, voiceSelection, audioConfig);

            var result = _mp3Helper.SaveFile(response);
            if (result.Item1 == "Success")
                return Json(new { Result = true, Value = result.Item2 });
            else
                return Json(new { Result = false, Error = result.ToString() });
        }
        catch(Exception ex)
        {
            return Json(new { Result = false, Error = ex.Message.ToString() });
        }

The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.

Sakshi Gatyan
  • 1,903
  • 7
  • 13
  • I wouldn’t hardcore that path! – Daniel A. White Mar 15 '22 at 12:06
  • It is best to use Net 4.7.2 or later and target Core 3.1 to avoid encryption issues with TLS. Google requires HTTPS Secure (not HTTP) which uses TLS for encryption. With Net 4.7.2 TLS uses for default the Operating System to do TLS (Not Net) and fixed issue with encryption issues with the Net algorithms. Authentication is performed along with the encryption. I suspect the connection is failing due to the encryption and not due to the Authentication. – jdweng Mar 15 '22 at 12:18
  • @jdweng i tried with Net 4.7.2 but still not working and gave me the same error – Lorenzo Vettori Mar 15 '22 at 15:01
  • What error (response status code or exception)? Using HTTPS the TLS is performed before the request is sent. So when TLS fails you do not get a response, but may get an exception. If TLS passes you should get a response with a status code. If TLS fails with 4.7.2 or later than either the certificate is not matching in client and server or the Operating System needs updating (kernel) to support the latest versions of TLS (1.2 or 1.3). It is also possible that SSL or TLS 1.1 is being used and fails due to these versions being obsolete. – jdweng Mar 15 '22 at 15:58
  • Your problem is that you are setting up credentials incorrectly. You are mixing declaring a service account for **storage** and using ADC (Application Default Credentials) for **TextToSpeech**, Either the service account **path** is wrong or you have incorrectly setup the VM's attached service account or the VM **scopes**. More details are required to help you. – John Hanley Mar 15 '22 at 22:29

1 Answers1

3

Assuming you want to use the same service account for both Speech and Storage, you need to specify the credentials for the text-to-speech client. Options:

  • Set the GOOGLE_APPLICATION_DEFAULT_CREDENTIALS environment variable to refer to the JSON file. Ideally, do that as part of deployment configuration rather than in your code, but you can set the environment variable in your code if you want to. At that point, you can remove any explicit loading/setting of the credential for the Storage client.
  • Specify the CredentialPath in TextToSpeechClientBuilder:
    var client = new TextToSpeechClientBuilder { CredentialPath = path }.Build();
    
    This will load a separate credential.
  • Specify the credential's token access method via the TokenAccessMethod property in TextToSpeechClientBuilder:
    var client = new TextToSpeechClientBuilder
         {
             TokenAccessMethod = credential.GetAccessTokenForRequestAsync
         }.Build();
    
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194