Ahad Porkar
Ahad Porkar

Reputation: 1698

GoogleOAuth2 always return access denied to callback url

Im trying to Use GoogleAuthenticationExtensions from Microsoft.Owin.Security.Google

package inside MVC5 program. This is my StartUp.cs :

   var googlePlusOptions = new GoogleOAuth2AuthenticationOptions {};
    googlePlusOptions.ClientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com";
    googlePlusOptions.AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/auth";
    googlePlusOptions.TokenEndpoint = "https://oauth2.googleapis.com/token";
    googlePlusOptions.ClientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    googlePlusOptions.CallbackPath = new PathString("/GoogleLoginCallback");
    app.UseGoogleAuthentication(googlePlusOptions);

And SignInMethod method inside LoginController :

[HttpGet]
[AllowAnonymous]
public void SignInGoogle(string ReturnUrl = "/", string type = "")
{
    if (!Request.IsAuthenticated)
    {
        if (type == "Google")
        {
            var owinContext = HttpContext.GetOwinContext();
            owinContext.Authentication.Challenge(new AuthenticationProperties { RedirectUri = "Login/GoogleLoginCallback" }, "Google");
            Response.StatusCode = 401;
            Response.End();
        }
    } 
}

And CallBack Url in same controller :

[AllowAnonymous]
    public ActionResult GoogleLoginCallback()
    {
        var claimsPrincipal = HttpContext.User.Identity as ClaimsIdentity;

        var loginInfo = GoogleLoginViewModel.GetLoginInfo(claimsPrincipal);
        if (loginInfo == null)
        {
            return RedirectToAction("Index");
        }



        var user = db.UserAccounts.FirstOrDefault(x => x.Email == loginInfo.emailaddress);

        if (user == null)
        {
            user = new UserAccount
            {
                Email = loginInfo.emailaddress,
                GivenName = loginInfo.givenname,
                Identifier = loginInfo.nameidentifier,
                Name = loginInfo.name,
                SurName = loginInfo.surname,
                IsActive = true
            };
            db.UserAccounts.Add(user);
            db.SaveChanges();
        }

        var ident = new ClaimsIdentity(
                new[] { 
                            // adding following 2 claim just for supporting default antiforgery provider
                            new Claim(ClaimTypes.NameIdentifier, user.Email),
                            new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),

                            new Claim(ClaimTypes.Name, user.Name),
                            new Claim(ClaimTypes.Email, user.Email),
                            // optionally you could add roles if any
                            new Claim(ClaimTypes.Role, "User")
                },
                CookieAuthenticationDefaults.AuthenticationType);


        HttpContext.GetOwinContext().Authentication.SignIn(
                    new AuthenticationProperties { IsPersistent = false }, ident);
        return Redirect("~/");

    }

Now Program goes into Login Screen Of Google but when it came back into Call Back Url the

loginInfo is null. This is the response from Call Back Url :

enter image description here

Things ive done so far without any result : 1-Activating Google+ APi 2-Updating the nuget to latest version (4.2 atm) 3-Add Email to TestUser or change project inside google console to production 4-Add and fill consent part in google console 5-set the js callback to blank

one thing that is kinda strange is that , if i modify ClientId the login screen of google will stop me but if i change secretId nothing will happen and still i see the error above. Ive got both of them (ClientId,SecretId) today from OAuth console panel today.

Upvotes: 2

Views: 1112

Answers (1)

jgasiorowski
jgasiorowski

Reputation: 1033

With these kind of questions it is really hard to point exactly where the problem sits without recreating your full environment setup. So I can only try to explain what is happening but for more precise solution you will have to dig more into it.

Basically I am not sure how much do you know about OpenIDConnect and OAuth2.0 flows but I can describe what is happening in your scenario.

  1. Your application is redirecting user to google login page
  2. User is logging in
  3. After successful login google redirects user browser back to your application with those query parameters (third row on your screen shot)
  4. Now your application should take those parameters and send it to google in backchannel (server to server request) to exchange it for access_token from google. Here is a tricky part - probably you think that you are executing GoogleLoginCallback method immediately - but you don't. What is really happening is that GoogleAuthentication Middleware is taking that responsibility. It identifies that request is part of OpenIDConnect flow and will try to get the token for you and setup Identity in your context.
  5. Unfortunately something goes wrong because you get another redirection with ?error=access_denied parameter. This is done exactly by GoogleOAuth2AuthenticationHandler implementation from Katana project: https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L259 here is the code which is doing that. I think you should use this repository to identify the flow and what could go wrong (looks like your context.Identity is null for some reason).
  6. Now on that redirect you are finally executing your controller method GoogleLoginCallback But I guess because previous step failed - we don't have correct state of identity in that request.

You have not shared more of your Startup.cs but you should use .UseCookieAuthentication() as shown in Katana sample https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/samples/Katana.Sandbox.WebServer/Startup.cs#L83

Definitely what I think you need to change is you need to change or remove setting CallbackPath property which is used to identify OpenID flow step https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L224. This callback is only for the purpose of exchanging for the access token and default value is /signin-google https://github.com/aspnet/AspNetKatana/blob/dbe159e43e2eee44f315f26268943e8ab5a4f60d/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationOptions.cs#L28 So GoogleAuthenticationHandler will kick in everytime you will try to access your controller method.

Sorry if this still does not help. But I think you should have enough sources to slowly find your solution. What I would suggest if you still will not be able to identify the problem is to copy classes from Katana github into your project, rename and then whole flow should be 'debbugable'.

And to answer your last question:

Upvotes: 2

Related Questions