GoogleWebAuthorizationBroker problem, but in a .NET Framework 4.8 application

67 Views Asked by At

I have a problem with the Google Gmail API. It is working on my local machine, but once I deploy the project to the server, it stops working.

Error:

System.AggregateException: One or more errors occurred. ---> System.NotSupportedException: Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&code_challenge=tDq__xCgypmYKgfwjD0nAcV7mMU6rWMS2Hm_UqPqbTY&code_challenge_method=S256&response_type=code&client_id=180884391537-6lvtccf5rot6a124v9qb4coilhmtv3fe.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A64176%2Fauthorize%2F&scope=https%3A%2F%2Fmail.google.com%2F%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.modify%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.send%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email" for authorization. See inner exception for details. ---> System.ComponentModel.Win32Exception: Access is denied
   at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start()
   at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
   at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.OpenBrowser(String url)
   at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.<ReceiveCodeAsync>d__13.MoveNext()
   --- End of inner exception stack trace ---
   at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.<ReceiveCodeAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Google.Apis.Auth.OAuth2.AuthorizationCodeInstalledApp.<AuthorizeAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.<AuthorizeAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.<AuthorizeAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.<AuthorizeAsync>d__1.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()

I have an application in .NET Framework 4.8 where I want to access Gmail emails from accounts that users associate in my application. In the Google Developer Console, I created OAuth 2.0 credentials for a web application and also for a desktop application. At the local level it works very well because we use GoogleWebAuthorizationBroker, but in production an error appears, when it is a web application this method does not allow me to authenticate or authorize Google accounts to return the tokens. I asked about Google.Apis.Auth.AspNetCore3, but my understanding is that it works in .NET Core 3 applications, not the .NET Framework. I don't know what it is or where to start. The code is the following:

        private static readonly string credentialsPathDesktop = HttpContext.Current.Server.MapPath("~/App_Data/IntegracionesCRM/Credentials/Google/client_secrets.json");
        private static readonly string credentialsPathWebApp = HttpContext.Current.Server.MapPath("~/App_Data/IntegracionesCRM/Credentials/Google/client_secret_webApp.json");
        private static readonly string[] Scopes = { Scope.MailGoogleCom, Scope.GmailModify, Scope.GmailSend, "https://www.googleapis.com/auth/userinfo.email" };

        // Authorizing a service account with workspace
        public LoadServiceGoogle LoadGoogleCredentials(int gdtnegociotipo)
        {
            context.Configuration.LazyLoadingEnabled = false;
            var tipo = context.gdtnegociotipoes.SingleOrDefault(x => x.gdtnegociotipoid == gdtnegociotipo);

            using (var stream = new FileStream(credentialsPathDesktop, FileMode.Open, FileAccess.Read))
            {
                var clientSecrets = GoogleClientSecrets.FromStream(stream).Secrets; // Accede a la propiedad Secrets del objeto GoogleClientSecrets

                try
                {
                    // Genering a random user id to avoid conflicts
                    string userIdPrefix = "user_";
                    string userId = userIdPrefix + Guid.NewGuid().ToString();
                    string tokensPath = HttpContext.Current.Server.MapPath(string.Format("~/App_Data/IntegracionesCRM/Tokens/TiposID/{0}", tipo.gdtnegociotipoid));

                    UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                                           clientSecrets,
                                           Scopes,
                                           userId,
                                           CancellationToken.None,
                                           new FileDataStore(tokensPath)).Result;

                    return new LoadServiceGoogle { credential = credential, tokensFolderPath = tokensPath, credentialsPath = credentialsPathDesktop, userId = userId };
                }
                catch (Exception ex)
                {
                    throw new SecurityAccessDeniedException("Error al obtener las credenciales de Google", ex);
                }
            }
        }
1

There are 1 best solutions below

1
Linda Lawton - DaImTo On

GoogleWebAuthorizationBroker.AuthorizeAsync is designed for use with installed applications and won't work on a web app as it will attempt to open the consent screen on the machine that the code is running on in this case your web server basically you're using the wrong code

Unfortunately I'm not aware of any working sample code for really old versions of done that so I can't be of much more help