8

I am new to MVC 5 authentication. Currently I tried Google Authorization using Owin The code in startup.Auth.cs

var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions
{
    ClientId = "Client-id",
    ClientSecret = "secret-key",
    CallbackPath = new PathString("/Account/ExternalLoginCallback"),
    Provider = new GoogleOAuth2AuthenticationProvider()
    {
        OnAuthenticated = async context =>
        {
            context.Identity.AddClaim(new Claim("picture", context.User.GetValue("picture").ToString()));
            context.Identity.AddClaim(new Claim("profile", context.User.GetValue("profile").ToString()));
        }
    }
};
googleOAuth2AuthenticationOptions.Scope.Add("email");

app.UseGoogleAuthentication(googleOAuth2AuthenticationOptions);

But it does not hit ExternalLoginCallback Action for debug.

[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)

It stop at /Account/ExternalLoginCallback?ReturnUrl=%2F with blank white screen. I won't find what is wrong with this. and find similar question Google Authentication using OWIN Oauth in MVC5 not hitting ExternalLoginCallback function, but it is not helpful in mine case.

Community
  • 1
  • 1

5 Answers5

5

This is similar to: Google Authentication using OWIN Oauth in MVC5 not hitting ExternalLoginCallback function

Basically, set your google App in the Developers dashboard to point to your */ExternalLoginCallback method.

Leave the GoogleProvider with the default callback path.

var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions
    {
        ClientId = "MYCLIENTID",
        ClientSecret = "MYSECRET"
    };

Add a route to handle signin-google in RouteConfig:

routes.MapRoute(
            name: "signin-google",
            url: "signin-google",
            defaults: new { controller = "[YOURCONTROLLLER]", action = "ExternalLoginCallback"});

That should fix google provider and all the others too.

Community
  • 1
  • 1
Rodrigo
  • 234
  • 1
  • 6
2

Try this it may work. Its works for my case

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
                {
                    ClientId = "YourClintId",
                    ClientSecret = "YourSecretKey",
                    CallbackPath = new PathString("/Account/ExternalLoginCallback")
                });
1

I've been having issues with setting up Owin/Katana/Oath etc.

In short...

  1. Clear your browser history
  2. Leave the GoogleOAuth2AuthenticationOptions.CallbackPath as the default
  3. There should be two entries in the Google "Authorised redirect URIs": https://domain[:port]/signin-google and https://domain[:port]/MVCController/MVCAction

In long...

Clear your browser history. I've been trying to learn OWIN/Katana etc for the past few days and have been making many configuration changes on the Google Developer Console and within my code. I was occasionally getting the "white screen" and unable to get the debugger to hit code within my ExternalLoginCallback() function. Clearing my browser history seems to fix this.

There is no need to set the GoogleOAuth2AuthenticationOptions.CallbackPath, leave it as the default signin-google.

I'm testing locally so I've set my the Google credentials to (replacing the port number with the one you're using!)

Authorised Javascript Origins : "https://localhost:44353"

Authorised redirect URIs: "https://localhost:44353/signin-google" and "https://localhost:44353/Account/ExternalLoginCallback"

Overly verbose code if anyone is interested

Startup.Auth.cs

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        var cookieAuthenticationProvider = new CookieAuthenticationProvider();

        var cookieAuthenticationOptions = new CookieAuthenticationOptions();
        cookieAuthenticationOptions.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie;
        cookieAuthenticationOptions.LoginPath = new PathString("/Account/Login");
        cookieAuthenticationOptions.Provider = cookieAuthenticationProvider;

        app.UseCookieAuthentication(cookieAuthenticationOptions);

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions();
        googleOAuth2AuthenticationOptions.ClientId = "TODO : add client id";
        googleOAuth2AuthenticationOptions.ClientSecret = "TODO : add secret";

        app.UseGoogleAuthentication(googleOAuth2AuthenticationOptions);
    }
}

Function executed when user clicks my "Sign in with Google". provider will be "Google"

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public void ExternalLogin(string provider)
{
    var properties = new Microsoft.Owin.Security.AuthenticationProperties();

    properties.RedirectUri = Url.Action("ExternalLoginCallback", "Account");

    HttpContext.GetOwinContext().Authentication.Challenge(properties, provider);
}

Function that will be executed when user returns from Google.

[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback()
{
    var loginInfo = await Microsoft.Owin.Security.AuthenticationManagerExtensions.GetExternalLoginInfoAsync(HttpContext.GetOwinContext().Authentication);

    if (loginInfo == null)
    {
        throw new NotImplementedException();
    }

    var signInResult = await this.SignInManager.ExternalSignInAsync(loginInfo, false);

    if (signInResult == Microsoft.AspNet.Identity.Owin.SignInStatus.Success)
    {
        return RedirectToAction("Index", "Home");
    }

    if (signInResult == Microsoft.AspNet.Identity.Owin.SignInStatus.RequiresVerification)
    {
        // ...
    }

    /// etc...
}
Kevin Brydon
  • 12,524
  • 8
  • 46
  • 76
-1

You have add the follow in order to map the route in RouteConfig.cs because Google sends the response to yourdomain/signin-google.

public static void RegisterRoutes(RouteCollection routes)
        {
            ...

            routes.MapRoute(name: "signin-google", url: "signin-google", defaults: new { controller = "Account", action = "ExternalLoginCallback" });
        }
spadelives
  • 1,588
  • 13
  • 23
  • You do not. OWIN handles this url directly, and whether you add a Route for it or not, that occurs at the MVC level, after OWIN. Since OWIN handles /signin-google for you before it'd ever hit MVC, the Route is irrelevant, and OWIN handles this step just fine on its own. – Chris Moschini Apr 28 '15 at 13:29
  • 1
    That is totally not the case Chris. Google ALWAYS send the result back to signin-google. If you don't bind this URL with a local action by configuring the route, you can't process the result. – spadelives May 01 '15 at 02:33
  • 1
    That's what's confusing you. You should not process the result. You are correct that Google fires back to /signin-google, though it's important to note that Google does this because OWIN asks it to. But, OWIN then processes the Request to /signin-google. Even if you do register a Route etc as you have above, **it will not do anything**, because OWIN is handling requests and handles this one before it would delegate it to MVC/Routing. See more here http://stackoverflow.com/a/29921451/176877 – Chris Moschini May 01 '15 at 23:23
  • I think the question was about how to get the workflow to hit the ExternalLoginCallback method, which the mapping does accomplish. Out of curiosity, if you don't use the mapping but you do need to process the result (e.g. in our case to parse the user's legacy Google ID), where can you access the result if not in ExternalLoginCallback? – spadelives May 14 '15 at 04:50
  • That should be posted as its own question here on SO, very different, specific scenario. The question isn't worded well so it's unclear whether they were just asking why is a standard Google/OWIN/OpenId failing at this step for me, or something more narrow like you're referring to. I'm assuming the more general case, because it's easy to run into this problematic outcome in a standard config, and because more people are likely to land here looking for the general answer. – Chris Moschini May 14 '15 at 19:34
-1

Try the same code but change the CallbackPath to /umbraco/surface/UmbracoIdentityAccount/LinkLoginCallback and register it in the Authorized redirect URIs in your app.

mmvsbg
  • 3,570
  • 17
  • 52
  • 73
chezza
  • 1