1

i'd like to use gmail api in asp.net web api project. This is what i have so far:

        UserCredential credential;
        var cleantSecretPath = HostingEnvironment.MapPath("~/client_secret.json");
        var rootPath = HostingEnvironment.MapPath("~/");

        if (rootPath != null)
        {
            var credentialPath = Path.Combine(rootPath, "Credentials");
            var directoryInfo = Directory.CreateDirectory(credentialPath);
        }

        var credentialsPath = HostingEnvironment.MapPath("~/Credentials/");

        using (var stream = new FileStream(cleantSecretPath, FileMode.Open, FileAccess.Read))
        {
            var secret = GoogleClientSecrets.Load(stream).Secrets;
            var dataStore = new FileDataStore("test");
            credential = GoogleWebAuthorizationBroker.AuthorizeAsync(secret, Scopes, _credentials.Email, CancellationToken.None, dataStore).Result;
        }

        var service = new GmailService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = ApplicationName,
        });
        return

it works on local host but as soon as i deploy it to azure i receive an error:

<Error>
    <Message>An error has occurred.</Message>
    <ExceptionMessage>One or more errors occurred.</ExceptionMessage>
    <ExceptionType>System.AggregateException</ExceptionType>
    <StackTrace>
    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() at BL.GmailServiceBl.GetGmailService() in D:\Development\DotNetProjects\GmailAnalysis\BL\GmailServiceBl.cs:line 53 at BL.AnalysisService..ctor(PersonCredentials credentials) in D:\Development\DotNetProjects\GmailAnalysis\BL\AnalysisService.cs:line 22 at WebAPI.Controllers.ValuesController.Get(PersonCredentials credentials) in D:\Development\DotNetProjects\GmailAnalysis\WebAPI\Controllers\ValuesController.cs:line 63 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- 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 System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.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 System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.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 System.Web.Http.Controllers.AuthenticationFilterResult.<ExecuteAsync>d__0.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 System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
    </StackTrace>
    <InnerException>
        <Message>An error has occurred.</Message>
        <ExceptionMessage>Access is denied</ExceptionMessage>
        <ExceptionType>System.Net.HttpListenerException</ExceptionType>
        <StackTrace>
        at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task) at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.<AuthorizeAsync>d__1.MoveNext() in c:\code\github\google-api-dotnet-client\Tools\Google.Apis.Release\bin\Release\1.9.2\default\Src\GoogleApis.Auth.DotNet4\OAuth2\GoogleWebAuthorizationBroker.cs:line 59
        </StackTrace>
    </InnerException>
</Error>

i'm using client_secret.json for Web Application. Can some one give me an example or point me in a right direction.

Dima Daron
  • 548
  • 1
  • 7
  • 21

2 Answers2

0

Here's an example that works:

var filePath = HostingEnvironment.MapPath("~/build-info.json");
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
string fileContent;
using (var reader = new StreamReader(fileStream))
{
    fileContent = reader.ReadToEnd();
}

I have run this locally and deployed to an Azure WebApp and it works in both locations.

So something like the following should work:

UserCredential credential;
var filePath = HostingEnvironment.MapPath("~/client_secret.json");
using (var stream = new FileStream(filePath , FileMode.Open, FileAccess.Read))
{
    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
        new[] { GmailService.Scope.GmailReadonly },
        "user", CancellationToken.None);
}
viperguynaz
  • 12,044
  • 4
  • 30
  • 41
  • Hey @viperguynaz thank you for your help, but if you using await, the credential does not return. if you'll change the code like that : `credential =GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, new[] { GmailService.Scope.GmailReadonly }, "user", CancellationToken.None).Result;` you will get the access is denied error – Dima Daron Oct 18 '15 at 10:07
0

After a few days tackling a similar problem I found out that this is not how you should do it:

credential = GoogleWebAuthorizationBroker.AuthorizeAsync(secret, Scopes, _credentials.Email, CancellationToken.None, dataStore).Result;

Instead, you should use the FlowMetadata approach to authenticate, demonstrated here.

Community
  • 1
  • 1
Shiran Dror
  • 1,472
  • 1
  • 23
  • 36