在ExternalLogin函数调用之后未触发ExternalLoginCallback - Google OAuth

时间:2015-08-11 10:36:14

标签: asp.net asp.net-mvc oauth-2.0 google-plus

我正在开发一个使用Google+进行外部身份验证的ASP.NET MVC 5应用程序。我在console.developers.google.com上创建了一个项目,获得了appID和appSecret。以下是UI和代码。我无法发布图片,因为我需要10个以上的声誉:(。我的登录屏幕包含呈现所有ExternalLogin提供商的部分视图。我已按以下方式注册Google提供商。

 public partial class Startup
{
    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });            
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
        app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));

        // Enables the application to remember the second login verification factor such as phone or email.
        // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
        // This is similar to the RememberMe option when you log in.
        app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

        // 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("xxxxxxxxxx_my_appID",
        "xxxxx_my_appsecret");

    }

来自RouteConfig.cs的代码

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {

        routes.MapRoute(
           name: "signin-google",
           url: "signin-google",
           defaults: new { controller = "Account", action = "ExternalLoginCallback" }
       );
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

    }
}

点击&#34;使用Google登录&#34;按钮,调用以下代码。

  [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 }));
    }

[AllowAnonymous]
    public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

        if (loginInfo == null)
        {
            return RedirectToAction("Login");
        }

        //This will fetch the USERPROFILE from google
        if (loginInfo.Login.LoginProvider == "Google")
        {
            var externalIdentity = AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);

            var emailClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email);
            var lastNameClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname);
            var givenNameClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName);
            //var DOBClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.DateOfBirth);
            //var genderClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Gender);
            //var LocClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Locality);
            //var countryClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Country);
            //var mobileClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.);
            var accesstoken = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type.Equals("urn:tokens:google:accesstoken"));
            var Photo = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type.Equals("urn:tokens:google:accesstoken"));
            var userid = loginInfo.ExternalIdentity.GetUserId();

            var email = emailClaim.Value;
            var firstName = givenNameClaim.Value;
            var lastname = lastNameClaim.Value;
            var token = accesstoken.Value;
            Session["FullName"] =   firstName + " " +lastname;
            Session["FName"] = firstName;
            Session["LName"]= lastname;
            Session["Email"] = email;
            Session["GoogleAccessToken"] = token;
            Session["UserID"] = userid;
            //get access token to use in profile image request
           // var accessToken = loginInfo.ExternalIdentity.Claims.Where(c => c.Type.Equals("urn:google:accesstoken")).Select(c => c.Value).FirstOrDefault();
            Uri apiRequestUri = new Uri("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token);
            //request profile image
            using (var webClient = new System.Net.WebClient())
            {
                var json = webClient.DownloadString(apiRequestUri);
                dynamic result_pic = JsonConvert.DeserializeObject(json);
                Session["PhotoURL"] = result_pic.picture.Value;
            }

        }

        // Sign in the user with this external login provider if the user already has a login
        var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);

        switch (result)
        {
            case SignInStatus.Success:
                {
                    Session["ProviderKey"] = loginInfo.Login.ProviderKey;
                    Session["Provider"] = loginInfo.Login.LoginProvider;
                    return RedirectToLocal(returnUrl);

                }
            case SignInStatus.LockedOut:
                return View("Lockout");
            case SignInStatus.RequiresVerification:
                return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
            case SignInStatus.Failure:
            default:
                // If the user does not have an account, then prompt the user to create an account
                ViewBag.ReturnUrl = returnUrl;
                ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
        }
    }

问题是,ExternalLoginCallback没有被调用,并且登录过程不完整。当我使用开发人员工具深入挖掘请求/响应时,我发现响应是状态&#39; 302 Found&#39;。

支持代码如下,

   internal class ChallengeResult : HttpUnauthorizedResult
    {
        public ChallengeResult(string provider, string redirectUri)
            : this(provider, redirectUri, null)
        {
        }

        public ChallengeResult(string provider, string redirectUri, string userId)
        {
            LoginProvider = provider;
            RedirectUri = redirectUri;
            UserId = userId;
        }

        public string LoginProvider { get; set; }
        public string RedirectUri { get; set; }
        public string UserId { get; set; }

ChallengeResult()方法调用ExecuteResult(下面),帖子我得到了Google错误:400-redirect_uri_mismatch

        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);
        }
    }

我检查了这些帖子并相应地修改了代码,但问题仍然存在。 Why MVC 5 Owin Oauth is not hitting /Account/ExternalLoginCallback action

GoogleOauth2 Issue Getting Internal Server 500 error

0 个答案:

没有答案