While reading the blog post, it became apparent to me that there should be a similar example showing how to Sign-in with Google and access Google APIs within an MVC 5 application. I chose to write a simple sample to display the user's files form his or her Google Drive account using Google Drive API.
* All the code of this tutorial is available in https://github.com/peleyal/peleyal.git.
* UPDATE (Dec 2014) *
Google OpenID is deprecated please use OAuth 2.0 for accessing Google APIs.
More information about migrating OpenID to OAuth 2.0 is available at: https://developers.google.com/+/api/auth-migration.
Prerequisite:
The pre-requisites for this tutorial are the same as those in Rick's example.First, install Visual Studio Express 2013 for Web or Visual Studio 2013.
Next, create a new ASP.NET MVC application (I chose to call my application GoogleApis.Sample.MVC) with the default individual user account.
Continue as described in the article. Make sure to uncomment the following line: app.UseGoogleAuthentication();
It's located in ConfigureAuth method in App_Start\Startup.Auth.cs file)
Let's start:
1. Install NuGet packages
- Install the Google.Apis.Drive prerelease NuGet package.
- Install the Google.Apis.Auth.MVC prerelease NuGet package.
2. OAuth 2.0
Follow the OAuth 2.0 page for ASP.NET MVC applications. I'll repeat the key instructions in this section.2.1 Create a new AppAuthFlowMetadata that inherits from FlowMetadata.
In my sample I added the following class to Controllers folder.
using System;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Mvc;
using Google.Apis.Drive.v2;
using Google.Apis.Util.Store;
namespace Google.Apis.Sample.MVC.Controllers
{
public class AppAuthFlowMetadata : FlowMetadata
{
private static readonly IAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "PUT_CLIENT_ID_HERE",
ClientSecret = "PUT_CLIENT_SECRET_HERE"
},
Scopes = new[] { DriveService.Scope.Drive },
DataStore = new FileDataStore("Google.Apis.Sample.MVC")
});
});
public override string GetUserId(Controller controller)
{
return controller.User.Identity.GetUserName();
}
public override IAuthorizationCodeFlow Flow
{
get { return flow; }
}
}
}
- Make sure to replace the ClientID and ClientSecret values with the client secrets from your Google Developers Cloud project.
- Note: In my next blogpost I'll share a new implementation of EFDataStore to add support for Entity Framework as a storage mechanism.
- I used the Microsoft.AspNew.Identity.GetUserName() extension method to get the user identity. Because I've configured the application to use the Google flow, the identity returned from this object corresponds to the user who authenticated to this site.
2.2 Create your Auth callback
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Google.Apis.Sample.MVC.Controllers
{
public class AuthCallbackController :
Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
{
protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData
{
get { return new AppAuthFlowMetadata(); }
}
}
}
Later on, I'll create the service object for accessing the Google Drive API.
2.3 Register the Auth address into your Cloud project
Get the project URL from your project file inside VS2013. Then register that URI in your Google Developers Console project.
As you can see in the above images, I registered http://localhost:49244/AuthCallback/IndexAsync as a Redirect URI to my cloud project (Visual Studio picked 49244 port to my web application).
Make sure you also enable the Drive API in the APIs tab.
Make sure you also enable the Drive API in the APIs tab.
3. Get files from the DriveService
In this step we will create a DriveService instance and fetch all the user's files.
3.1 Create a model for Drive's File
Before we can retrieve information about the user's Drive files, we should specify a "local" model (It's just a best practice).
using System;
namespace Google.Apis.Sample.MVC.Models
{
public class FileModel
{
public string Id { get; set; }
public class FileModel
{
public string Id { get; set; }
public string Title { get; set; }
public DateTime? CreatedDate { get; set; }
public string DownloadUrl { get; set; }
}
}
}
3.2 Add DriveAsync method to the HomeController
Start by adding the following using statements:
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Google.Apis.Sample.MVC.Models;
using Google.Apis.Auth.OAuth2.Mvc;
using Google.Apis.Download;
using Google.Apis.Drive.v2;
using Google.Apis.Services;
Next, add the following code to make an API call to Google Drive:
[Authorize]
public async Task<ActionResult> DriveAsync(CancellationToken cancellationToken)
{
ViewBag.Message = "Your drive page.";
var result = await new AuthorizationCodeMvcApp(this, new AppAuthFlowMetadata()).
AuthorizeAsync(cancellationToken);
if (result.Credential == null)
return new RedirectResult(result.RedirectUri);
var driveService = new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = result.Credential,
ApplicationName = "ASP.NET Google APIs MVC Sample"
});
var listReq = driveService.Files.List();
listReq.Fields = "items/title,items/id,items/createdDate,items/downloadUrl,items/exportLinks";
var list = await listReq.ExecuteAsync();
var items =
(from file in list.Items
(from file in list.Items
select new FileModel
{
Title = file.Title,
Id = file.Id,
CreatedDate = file.CreatedDate,
DownloadUrl = file.DownloadUrl ??
(file.ExportLinks != null ? file.ExportLinks["application/pdf"] : null),
(file.ExportLinks != null ? file.ExportLinks["application/pdf"] : null),
}).OrderBy(f => f.Title).ToList();
return View(items);
}
- Notice that the DriveAsync operation is marked with the Authorize attribute. In this case we use this attribute because we require users to log in before they granted access to this content.
- The result of AuthorizationCodeMvcApp.AuthorizeAsync is an AuthResult. The RedirectUri property is set in case the end-user needs to authorize. Otherwise the Credential property will be set with the user's credential.
- Then I create the service and it's list request. Notice that I set the Fields property of the request to fetch only the fields that I'm going to use in the view.
- I convert the Drive API file model into my sample model, order the list by title, and send it to the client.
4. UI changes
4.1 Add a new DriveAsync view under Views/Home
@model IEnumerable<Google.Apis.Sample.MVC.Models.FileModel>
@{
ViewBag.Title = "Drive";
}
<table>
<tr>
<th>
Title
</th>
<th>
</th>
</th>
</tr>
{
<tr>
<td>
@Html.DisplayFor(modelItem => file.Title)
</td>
</td>
{
title = file.Title,
downloadUrl = file.DownloadUrl
})
</td>
}
</table>
4.2 Change _Layout.cshtml to include a link to the new page
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Drive", "DriveAsync", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
Add only the highlighted line. All the rest lines of code are already exist in the file.
5. Run
The first page you are going to see when running the web application is the following:
To sign in, click on the Drive tab. The following screen shows he login page.
Choose Google as a service login.
Now you should login.
Approve the site to use the required scopes to view your email address and basic information.
Choose a user name.
The above screen might look weird to you.
You already approved the application to use your email and basic information, so you might wonder why do you need to approve again other scopes?
The reason you need to approve the other scopes when the user sign in the first time is to authenticate the user. In the above screen the user needs to authorize this site to access his or her Drive data.
We might want to avoid those duplicate steps in the future and try making both of them as a one step, but I'll leave it to the future.
We are DONE!
6. Coming Next
- Download a file using MediaDownloader
- Implement a new EFDataStore - Entity Framework implementation of IDataStore.
- Any suggestions?
And I know that you are curious about the photo of this post... It's Prague! And unfortunately not in a sunny day.
Prague Oct 2009 |
Thanks for the detailed post. I was trying to do this on a MVC4 application, but couldn't get it to work. When I initiate the OAuth workflow, it throws the exception ... Could you help me figure out the issue?
ReplyDeleteThanks in advance.
[KeyNotFoundException: The given key was not present in the dictionary.]
System.Collections.Generic.Dictionary`2.get_Item(TKey key) +14379623
Google.Apis.Auth.OAuth2.Mvc.Filters.AuthorizationCodeActionFilter.OnActionExecuting(ActionExecutingContext actionContext) in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\output\default\Src\GoogleApis.Auth.Mvc4\OAuth2\Mvc\Filters\AuthActionFilter.cs:34
System.Web.Mvc.Async.AsyncInvocationWithFilters.InvokeActionMethodFilterAsynchronouslyRecursive(Int32 filterIndex) +296
System.Web.Mvc.Async.AsyncInvocationWithFilters.InvokeActionMethodFilterAsynchronouslyRecursive(Int32 filterIndex) +1137
System.Web.Mvc.Async.<>c__DisplayClass33.b__31(AsyncCallback asyncCallback, Object asyncState) +112
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +132
System.Web.Mvc.Async.<>c__DisplayClass21.b__19(AsyncCallback asyncCallback, Object asyncState) +1449
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +96
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +487
System.Web.Mvc.Controller.b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +45
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +111
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +203
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +879
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +154
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +527
System.Web.Mvc.MvcHandler.b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +108
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +111
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150
System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +203
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +681
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +12270483
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
Figured out the problem. I had made the controller that started the OAuth dance to derive from Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController - which it should not. And we should have the AuthCallbackController as described in the blog.
ReplyDeleteAlso the sample code in GitHub also helped.
Thanks again for the post!
Did you get a chance to write about EFDataStore??
ReplyDeleteNot yet, but I'll try to add such an implementation for the next release.
ReplyDeleteRemember that this project is an open source, so you can contribute to this library as well :)
Anyway I created a new issue for this task in our issue tracker - https://code.google.com/p/google-api-dotnet-client/issues/detail?id=453
This comment has been removed by the author.
ReplyDeleteHi, I'm trying to implement AuthorizationCodeMvcApp but sometimes I've got the error:
ReplyDeleteServer Error in '/' Application.
Error:"State is invalid", Description:"", Uri:""
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"State is invalid", Description:"", Uri:""
I've noticed that when the this occurs the key stored in DataStore looks like:
System.String-oauth_3755e307-a676-4775-919b-bd15932e105e
instead of:
Google.Apis.Auth.OAuth2.Responses.TokenResponse-95e60596-f8a1-4f54-892f-36c4438e2516
Any help?
Thanks for all
Did you follow all the steps above?
DeleteWe generate a state parameter, so the server will be able to know that it was the one the redirect the user and it isn't just some malicious site.
I've followed all the steps, the only difference is that I'm trying to implement an EF Data Store
DeleteCan you first check that the file data store works correctly, and by that we will eliminate the possibility that the EF data store is doing something wrong?
DeleteThanks
I have exactly the same issue trying to implement my custom IDataStore. Can you please share one example how to do it Peled? Thanks a lot
Delete@sfyenterprise sfyenterprise Did you succeed in the end? If so can you please share how to implement the IDataStore with Entity Framework ? Thanks
DeleteHi, thanks for wonderful tutorial, but I my program is stuck at "return new RedirectResult(result.RedirectUri);".
ReplyDeleteIt is not redirecting to Google Login page. What could be the possible reasons for this???
What is the content of result.RedirectUri?
DeleteWhat do you mean by saying it stuck? The program is stuck?
Please double check that you followed all the instructions :)
Stuck means...there was no response And the result.RedirectUri is correct but now...its stuck at "var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);"
DeleteThis comment has been removed by the author.
DeleteIt's hard to tell, do you use async-await correctly?
DeleteDo you want to share your code with me, so I'll be able to advice better. Try to create a small app that contains only your error and send it to me.
I have shared my project folder here https://onedrive.live.com/redir?resid=5AADC9FDACC3AC51!1700&authkey=!ALS_3jJl1hDEtbs&ithint=file%2czip
DeleteIt is VS 2010 solution...
I'm getting several warning and errors like those ones: (consider using VS2012 or higher)
DeleteWarning 6 The primary reference "Microsoft.Threading.Tasks.Extensions" could not be resolved because it has an indirect dependency on the framework assembly "System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which could not be resolved in the currently targeted framework. ".NETFramework,Version=v4.0". To resolve this problem, either remove the reference "Microsoft.Threading.Tasks.Extensions" or retarget your application to a framework version which contains "System.Threading.Tasks, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". MyMail
Warning 14 The primary reference "Microsoft.Threading.Tasks.Extensions" could not be resolved because it has an indirect dependency on the framework assembly "System.Runtime, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which could not be resolved in the currently targeted framework. ".NETFramework,Version=v4.0". To resolve this problem, either remove the reference "Microsoft.Threading.Tasks.Extensions" or retarget your application to a framework version which contains "System.Runtime, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". MyMail
Error 6 The type or namespace name 'Util' does not exist in the namespace 'Google.Apis' (are you missing an assembly reference?) C:\Users\peleyal\Downloads\MyMail\MyMail - Copy\MyMail\Controllers\DriveAppFlowMetadataController.cs 7 19 MyMail
Error 12 The type or namespace name 'Util' does not exist in the namespace 'Google.Apis' (are you missing an assembly reference?) C:\Users\peleyal\Downloads\MyMail\MyMail - Copy\MyMail\Controllers\AppAuthFlowMetadata.cs 9 19 MyMail
Error 20 The type or namespace name 'Util' does not exist in the namespace 'Google.Apis' (are you missing an assembly reference?) C:\Users\peleyal\Downloads\MyMail\MyMail - Copy\MyMail\Controllers\DriveController.cs 13 19 MyMail
I'm pretty sure that moving to VS2012 will solve most of those issues for me, and we might be able to continue from there..
Makes sense?
Sorry,
Eyal
I dont have VS 2012 and can not install VS2012 on my machine....could you plz try guide me to successfully run this project in VS2010....thanx :)
DeleteHi Eyal, very much thankful for this great post.
ReplyDeletewhen probably you will post to download file.
And is it possible to download file which is PRIVATE in share.
Take a look in this sample: https://code.google.com/p/google-api-dotnet-client/source/browse/Drive.Sample/Program.cs?repo=samples#154.
DeleteYou can also read more about media download here: https://developers.google.com/api-client-library/dotnet/guide/media_download
I believe that if the file exists in your drive folders you will be able to download it...
Let me know if anything is missing...
as it were with a web application hosted in iis?
ReplyDeleteonly works on localhost?
This sample should work with IIS Express or any other host :)
Deletewhen I run the brand apliacacion access denied error and does not open the window permits
DeleteCan you attach the stacktrace or more information?
DeleteTake a look in this issue:https://code.google.com/p/google-api-dotnet-client/issues/detail?id=462&can=1&q=Milestone%3DRelease1.8.2&colspec=ID%20Type%20Component%20Status%20Priority%20Milestone%20Owner%20Summary.
This was a result of http://stackoverflow.com/questions/23405767/system-unauthorizedaccessexception-access-to-the-path-google-apis-auth-is-deni/23430287?noredirect=1#comment36108622_23430287 SO thread.
Hope that this helps you.
Access to the path 'Google.Apis.Sample.MVC' is denied.
DeleteDescription: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.UnauthorizedAccessException: Access to the path 'Google.Apis.Sample.MVC' is denied.
ASP.NET is not authorized to access the requested resource. Consider granting access rights to the resource to the ASP.NET request identity. ASP.NET has a base process identity (typically {MACHINE}\ASPNET on IIS 5 or Network Service on IIS 6 and IIS 7, and the configured application pool identity on IIS 7.5) that is used if the application is not impersonating. If the application is impersonating via , the identity will be the anonymous user (typically IUSR_MACHINENAME) or the authenticated request user.
To grant ASP.NET access to a file, right-click the file in File Explorer, choose "Properties" and select the Security tab. Click "Add" to add the appropriate user or group. Highlight the ASP.NET account, and check the boxes for the desired access.
The links that I attach above should help you.
DeleteTake a look in the SO thread that contains the following:
1.Go to the IIS
2.Under sites select the Default site
3.Add Permission
4.choose I_User object and give read/write access.
5.later you can automate this setting using a batch file and startup task.
no results, get the same error
DeleteDefault site, refer to my site or the Default IIS site?
DeleteNew error
DeleteXMLHttpRequest cannot load https://accounts.google.com/o/oauth2/auth?access_type=offline&response_type…:%2F%2Frh.joffroy.com%2FEmpleados%2FIndexAsync%3FIDEmpleado%3D313880436114. No. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
Let's track that down in SO, feel free to open a new thread with the google-api-dotnet-client tag. Hope that you already resolved that one :)
Deletewhen I run the brand apliacacion access denied error and does not open the window permits
ReplyDeletePlease show us an example of how to use refresh tokens. Asking the user for consent every hour is not good. Thanks
ReplyDeleteYou don't need to get the user consent every hour. This code already supports refreshing the token, as you can read in https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#credentials. Makes sense?
DeleteHi
ReplyDeleteGreat Post. Implemeting the code for my google calendar API works fine on my localhost but after hosting it to server it given me following error :
OpenID auth request contains an unregistered domain:
After googling I came to know that Google has deprecated the use of OAuth 2.0.
Please help me how can I resolve this error using in your above code and signin through Google+
I hope you will reply me asap.
Thanks for the Post.
What do you mean by saying "Google has deprecated the use of OAuth 2.0". I don't think it's true :)
DeleteThis comment has been removed by a blog administrator.
ReplyDeleteHi Eyal, I need your personal advice on choosing between Service account and Web Account for user authentication. I have a number of users who want to access Google apps and I need to authenticate them. Please suggest me the best Outh 2.0 mechanism. My application will be developed in Mvc5.
ReplyDeletebest regards,
It looks like you should use web authentication. Follow up the instructions on https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web_applications.
ReplyDeleteMore details about the different OAuth 2.0 protocols (not .NET specific) are available at: https://developers.google.com/accounts/docs/OAuth2.
hi eyal.thanks for this post.please help me for below question:
ReplyDeleteI am creating a website by mvc5.is there a way that let users upload file's to my google drive storage?
I think this Mvc5 example needs an update as I am getting "400: unregistered domain" error. Google has deprecated the use of openId 2.0 and this example is using the same. I request the author to confirm this and help us fix the error.
ReplyDeletebest regards,
This comment has been removed by the author.
DeleteI didn't run the sample lately... I'll find some time in the next days to update it if it is required. Anyway...
DeleteGoogle has deprecated OpenID 1.0 and given developers using OpenID 2.0 until April 2015 to migrate to OAuth 2.0.
For more information, see https://developers.google.com/+/api/auth-migration
The gist in OpenID is that Google is not allowing new registrations and the existing registrations will be turned down.
An alternative solution is to implement the GetUserId in the FlowMetadata class differently (without using OpenID).
@Eyal: thanks for quick reply. :) Actually I tried using googleplus sign-in as recommended by google but it fails with invalid redirect-uri. When I register my app with http://localhost:port/signin-google, no errors but the calls never reaches to AuthCallback Controller that means I am not authenticated to make call against drive api. please tell me how to fix this ? Where should I put AuthCallBack and FlowMetadata code ?
DeleteDid you follow our OAuth 2.0 page for web applications?
Deletehttps://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web_applications
"
Google APIs support OAuth 2.0 for Web Server Applications. In order to run the following code successfully, you must first add a redirect URI to your project in the Google Developers Console. Since you will use FlowMetadata and its default settings, set the redirect URI to your_site/AuthCallback/IndexAsync.
......"
I did follow the page, so did follow your tutorial. Here the code of my startup.cs
Deleteapp.UseGoogleAuthentication(
clientId: ".myid.apps.googleusercontent.com",
clientSecret: "secret ");
The redirect Uri "mysite/AuthCallback/IndexAsync" is registered in my developer console. Still I get the same error , that is "invalid redirect-uri". I also looked into Rick's updated blog..no help.
Hi Eyal : I managed to get worked Service account authentication in my web application project instead of a server-side account ... I hope I won't face any problems because of this. Please tell me if this will cause any problem.
ReplyDeletebest regards,
I'm not an expert of the API. Keep me tuned and worst case I'll refer you to the right people.
DeleteAlso.. if something doesn't work, consider creating a new thread in SO using google-api-dotnet-client tag. Thanks!
I meant - I'm not an expert of the specific API you're using (which I'm not sure yet - what it is - Drive, Youtube, Calendar, etc.).
DeleteI'm the right guy on issues about the core .NET library and its API.
I have solved the previous Redirect URI problem in this tutorial but a new error came up..
Deleteresult.Credential always returns null and sends me to execute the redirect uri.. I get re-authenticated again , receive the token, the program gets stuck. Why "result.Credential" is returning null , even if , I am getting authenticated successfully. ? I followed your tutorial word by word and even get logged in but result.Credential is null. please help me.
ReplyDeleteReally nice and informative thanks for sharing this.
Web Development Company
thanks for the post this worked fine at my mvc web application. but in case user click cancel on google auth request page it gives Error:"access_denied", Description:"", Uri:""
ReplyDelete(http://localhost:*****/AuthCallback/IndexAsync?error=access_denied&state=http://localhost:*****/Home/gmailAsync15538256)
it tried to override the authcallback class method IndexAsync but i an un able to handle it. please suggest me if i am wrong some where or give some reference for google Oauth implementation sample using mvc.
I have downloaded this but it doesn't run in Visual Studio 2013?
ReplyDeleteError below
[NullReferenceException: Object reference not set to an instance of an object.]
Microsoft.Owin.Security.Cookies.d__0.MoveNext() +664
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24
Microsoft.Owin.Security.Infrastructure.d__2.MoveNext() +860
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
Microsoft.Owin.Security.Infrastructure.d__0.MoveNext() +427
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +22
Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow() +33
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +150
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +42
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +415
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
This comment has been removed by the author.
ReplyDeleteI know this has been out there for awhile, but I downloaded your project from GitHub. I was able to get it setup and running, but I'm having trouble on the Drive page. When I click on the "Google" button to login it throws a 404 error from Google. Did I miss a setting, or has this link changed?
ReplyDeleteNice details about asp.net mvc.
ReplyDeleteConvert ASP to ASP.Net