DotNetOpenAuth 4.3 and Google - OpenID 2.0 + OAuth

2019-01-17 12:30发布

If you want to cut to the chase, the question is: what is the best/official way to use DotNetOpenAuth with Google in asp.net mvc 5?

About a year ago, I used OAuth (DotNetOpenAuth oAuth and OpenID) pretty much as it came out of the box for asp.net MVC 4 (as it is in the sample project). Since then I used it successfully for google, facebook, yahoo and microsoft. However, recently I have been having intermittent problems with users signing into google. I have tried upgrading to MVC 5 and DotNetOpenAuth 4.3, but I get the same.

When I looked at the google docs I found this:

Important: Google has deprecated its support for OAuth 1.0. If you are using OpenID 2.0 + OAuth 1.0, we recommend that you switch to Google+ Sign-In. Google+ Sign-In provides the OAuth 2.0 authentication mechanism with rich social features and access to additional Google desktop and mobile features. It supports all Google users and transparent migration. For details, see the Migration of Google authentication.

I could very well be mistaken, by I thought that out-of-the-box asp.net mvc 4 DotNetOpenAuth uses OpenID 2.0 (I use minimumRequiredOpenIdVersion="V20") + OAuth 1.0. I can see in the DotNetOpenAuth source that there is an OAuth 2.0 library under 'product', but I am not sure how to use this. Also, I am a bit nervous about Auth 2.0 as what I have read is not very complementary and it seems that it is easier to shoot oneself in the foot (might be unfounded, but it seems to be a recurring theme).

For Google+ I found these instructions which seem pretty straightforward, but that is almost a year ago, so I am wondering if this is still the best way to go. I also found this git repository implementing Google oauth2. Still, I would like to know whether this is still relevant as it is all from some time ago.

So, the question is - what is the best/official way to use DotNetOpenAuth with Google in asp.net mvc5? Hopefully I haven't missed anything obvious, in which case just a pointer to some links will be fine.

Update I found this question and this question which are related. I guess that I will go with the google auth2 from git unless I am told otherwise.

Resolution

I did the following: -

  • Followed the steps in the link provided by the accepted answer. It is this link.

It's important to keep using SSL after login and not drop back to HTTP, your login cookie is just as secret as your username and password…redirecting back to HTTP after you’re logged in won’t make the current request or future requests much faster.

  • Got the latest DotNetOpenAuth.GoogleOAuth2 on Nuget.

  • I looked at the recommendation from this msdn blog (by the same author) about how to best to secure the site. Basically, the recommendation is to add the following which will force all pages to HTTPS:

    filters.Add( new System.Web.Mvc.RequireHttpsAttribute() );

Ultimately what this means is that the whole site is HTTPS. Since making those changes, the site has been running fine.

2条回答
欢心
2楼-- · 2019-01-17 13:12

Here is the recommended way to use Google authentication as well as a few other social integrations:

http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on

In order to use oauth2 (assuming your using MVC)

  1. Enable the Google OpenID provider Open the App_Start\Startup.Auth.cs file and remove the comment characters in //app.UseGoogleAuthentication(); to enable Google authentication.

  2. Under Use another service to log in, click Google. The user is then redirected to the google site where you will enter your credentials.

If you don't have this file or folder "app_start", then you probably created a 'blank' project, instead of an "internet" project when you first created the solution. It's much easier (if planning on using external logins) to select 'internet application' when you first begin. Not sure what editor your using, but Visual Studio 2012/2013 make this ridiculously easy!

If your going to use OpenID which is now the recommended way, here is a great starting point: https://developers.google.com/accounts/docs/OpenID#settingup

Lastly, if you have access to NUGET through your editor like (Visual studio) , you'll find these tasks, like adding oAuth-1/2 or openId have been made very easy..

Here is a last link that would get you off in the right direction if the above doesn't really fit your build... With a few more details, I would be more than happy to help guide you to the best solution. One thing I can say is that oauth2 IS still very relevant and used in many applications today, and you wouldn't be wrong implementing this while starting a new project today - it would be the right way to go (or at least one of the right ways to go)... Hope some of this helps and isn't just going down a path you have already been down.

Hope all is well.

查看更多
狗以群分
3楼-- · 2019-01-17 13:24

This is how you use DotnetOpenAuth with Google/OAuth2.

First, reference the DotnetOpenAuth.Ultimate package from Nuget.

Then create a provider class and the profile model class

public class GoogleClient : WebServerClient
{
    private static readonly AuthorizationServerDescription GoogleDescription = 
        new AuthorizationServerDescription
    {
        TokenEndpoint = new Uri( "https://accounts.google.com/o/oauth2/token" ),
        AuthorizationEndpoint = new Uri( "https://accounts.google.com/o/oauth2/auth" ),
        ProtocolVersion = ProtocolVersion.V20
    };

    public const string ProfileEndpoint = "https://www.googleapis.com/oauth2/v1/userinfo";

    public const string ProfileScope = "https://www.googleapis.com/auth/userinfo.profile";
    public const string EmailScope = "https://www.googleapis.com/auth/userinfo.email";

    public GoogleClient()
        : base( GoogleDescription )
    {
    }
}

public class GoogleProfileAPI
{
    public string email { get; set; }

    private static DataContractJsonSerializer jsonSerializer = 
        new DataContractJsonSerializer( typeof( GoogleProfileAPI ) );

    public static GoogleProfileAPI Deserialize( Stream jsonStream )
    {
        try
        {
            if ( jsonStream == null )
            {
                throw new ArgumentNullException( "jsonStream" );
            }

            return (GoogleProfileAPI)jsonSerializer.ReadObject( jsonStream );
        }
        catch ( Exception ex )
        {
            return new GoogleProfileAPI();
        }
    }
}

Then, in your login page (login controller) have this code:

    private static readonly GoogleClient googleClient = new GoogleClient
    {
        ClientIdentifier = "client_id",
        ClientCredentialApplicator = ClientCredentialApplicator.PostParameter( "client_secret" )
    };

        // Page_Load of login page if WebForms
        // Login action of the Account controller if MVC 

        IAuthorizationState authorization = googleClient.ProcessUserAuthorization();
        if ( authorization == null )
        {
            // Kick off authorization request
            // Google will redirect back here
            Uri uri = new Uri( "http://your.application.address/login" );
            googleClient.RequestUserAuthorization( returnTo: uri, 
                scope: new[] { GoogleClient.ProfileScope, GoogleClient.EmailScope } );
        }
        else
        {
            // authorization. we have the token and 
            // we just go to profile APIs to get email (and possibly other data)
            var request =
                WebRequest.Create(
                    string.Format( "{0}?access_token={1}", 
                    GoogleClient.ProfileEndpoint, 
                    Uri.EscapeDataString( authorization.AccessToken ) ) );
            using ( var response = request.GetResponse() )
            {
                using ( var responseStream = response.GetResponseStream() )
                {
                    var profile = GoogleProfileAPI.Deserialize( responseStream );
                    if ( profile != null &&
                        !string.IsNullOrEmpty( profile.email ) )
                        FormsAuthentication.RedirectFromLoginPage( profile.email, false );
                }
            }
        }
查看更多
登录 后发表回答