Question

Have a weird thing happening here.

I have built an ASP.NET MVC5 website, and have local accounts working fine via ASP.NET Identity.

I am now trying to enable external authentication, but have some weirdness happening.

I'm certain I've followed the right steps. I have this in my Startup.Auth.cs:

    public void ConfigureAuth(IAppBuilder app)
    {
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login")
        });
        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Uncomment the following lines to enable logging in with third party login providers
        //app.UseMicrosoftAccountAuthentication(
        //    clientId: "",
        //    clientSecret: "");

        //app.UseTwitterAuthentication(
        //   consumerKey: "",
        //   consumerSecret: "");

        //app.UseFacebookAuthentication(
        //   appId: "",
        //   appSecret: "");

        app.UseGoogleAuthentication();
    }

When the user clicks on the link to logon with Google, the ExternalLogin method is called:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {
        // Request a redirect to the external login provider
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
    }

Which I have verified via debugging gets into the ExecuteResult method of the ChallengeResult class:

        public override void ExecuteResult(ControllerContext context)
        {
            var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
            if (UserId != null)
            {
                properties.Dictionary[XsrfKey] = UserId;
            }
            context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
        }

However, in the browser, nothing happens. I just get a blank page where I would expect a redirect to the Google signin page.

There are no errors reported at all.

The other funny thing is that I tried to create another MVC5 application, but I get a "Object reference not set to an instance of an object" popup in VS2013, and the resultant project is missing the Account controller that is usually there by default.

I've repaired the installation of VS2013, I have re-installed Update 1, and I've also updated all Nuget packages in the solution.

I've run out of ideas of where to go next.

Update 1 Thinking that this may be related to my PC, I've deployed the website to Azure, and the problem still persists. Does this mean it could be related to a missing assembly, and it's not being reported correctly? I've run fusionlog, but I see no binding failures.

Spinning up a new VM with a clean install of Windows 8 and VS2013 to see if I can get a new project working there.

Update 2 Ok, just ran another round of "network" capturing, and when the user selects the external provider, it DOES post to the ExternalLogin action, but the response is a 401 Unauthorized. What could be causing this?

Was it helpful?

Solution

Ok,

I figured out what (the important part) of the issue was.

Firstly, I still don't known why when I create an MVC project I don't get a scaffold'ed AccountController class.

However, it seems my issue is that my login button was passing "google" instead of "Google" as the provider.

Seriously!? I am a little surprised that casing would matter with the name of the provider, but there you go.

OTHER TIPS

This is not the answer to your question but it respond a very similar problem

If you had Owin 2.0 and you migrate to 2.1

The _ExternalLoginsListPartial need to change from this:

<button type="submit" class="btn btn-default" id="@p.AuthenticationType" name="Partner" value="@p.AuthenticationType" title="Log in using your @p.Caption account">@p.AuthenticationType</button>

to this

<button type="submit" class="btn btn-default" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">@p.AuthenticationType</button>

The only thing that change is the name of the button but that could break your head like mine and cost me 2 days of work to find the problem.

Maybe this is explained in the new Owin version, if not must be something to specify in capitals.

I've just ran into the same issue with my ASP.Net WebAPI server. I was passing the correct AuthenticationType into the challenge method but still getting a blank page.

Turns out the issue was the order I added the OAuth providers into the OWIN pipeline at startup. Roughly my working order:

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();

        var authServerOptions = new OAuthAuthorizationServerOptions
        {
        ...
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(authServerOptions);
        app.UseOAuthBearerAuthentication(OAuthBearerOptions);

        // Configure Google External Login
        GoogleAuthOptions = new GoogleOAuth2AuthenticationOptions()
        {
            ClientId = xxxx,
            ClientSecret = xxxx,
            Provider = new GoogleAuthProvider()
        };
        app.UseGoogleAuthentication(GoogleAuthOptions);

        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);

Previously I was adding the UseCors + UseWebApi methods before UseGoogleAuthentication method.

I found this post to be useful too: http://coding.abel.nu/2014/06/understanding-the-owin-external-authentication-pipeline/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top