使用Owin进行Twitter外部登录会在回调上提供HTTP 403(禁止访问)

时间:2018-07-04 07:23:54

标签: asp.net-mvc twitter oauth owin

我正在尝试实施Twitter登录/注册。在asp.net Web应用程序中,但在最后的回调中我得到了403 http状态。

我在twitter应用程序门户中配置了我的回调URL(我认为它们是正确的)

我提供了一些我想做的事情的背景

  1. 将用户拒之门外twitter犯罪
  2. 然后执行第一个回调(这里没有问题),我调用twitter api来获取用户详细信息。
  3. 获取用户详细信息后,我将返回质询结果,以便我可以获取用户身份并为此指定第二个回调
  4. 第二个回调不执行。

    有人可以向我指出我在做什么错吗?或者我该如何调试问题? 我知道twitter检查是否需要在应用开发者门户中设置回调URL,我从这个问题question

  5. 得知

这是我的代码和配置

app.UseTwitterAuthentication(new TwitterAuthenticationOptions()
        {
            ConsumerKey = "key",
            ConsumerSecret = "qCLLsuS79YDkmr2DGiyjruV76mWZ4hVZ4EiLU1RpZkxOfDqwmh",
            Provider = new Microsoft.Owin.Security.Twitter.TwitterAuthenticationProvider
            {
                OnAuthenticated = (context) =>
                {
                    context.Identity.AddClaim(new System.Security.Claims.Claim("urn:twitter:access_token", context.AccessToken));
                    context.Identity.AddClaim(new System.Security.Claims.Claim("urn:twitter:access_secret", context.AccessTokenSecret));
                    return Task.FromResult(0);
                }
            },
            BackchannelCertificateValidator = new Microsoft.Owin.Security.CertificateSubjectKeyIdentifierValidator(new[]
                   {
                      "A5EF0B11CEC04103A34A659048B21CE0572D7D47", // VeriSign Class 3 Secure Server CA - G2
                      "0D445C165344C1827E1D20AB25F40163D8BE79A5", // VeriSign Class 3 Secure Server CA - G3
                      "7FD365A7C2DDECBBF03009F34339FA02AF333133", // VeriSign Class 3 Public Primary Certification Authority - G5
                      "39A55D933676616E73A761DFA16A7E59CDE66FAD", // Symantec Class 3 Secure Server CA - G4
                      "‎add53f6680fe66e383cbac3e60922e3b4c412bed", // Symantec Class 3 EV SSL CA - G3
                      "4eb6d578499b1ccf5f581ead56be3d9b6744a5e5", // VeriSign Class 3 Primary CA - G5
                      "5168FF90AF0207753CCCD9656462A212B859723B", // DigiCert SHA2 High Assurance Server C‎A 
                      "B13EC36903F8BF4701D498261A0802EF63642BC3" // DigiCert High Assurance EV Root CA
                    }),
        });

调用twitter登录(我指定了第一个回调URL,这个有效)

[AllowAnonymous]
    public ActionResult TwitterRegistration()
    {
        string UrlPath = HttpContext.Request.Url.Authority;
        // pass in the consumerkey, consumersecret, and return url to get back the token
        NameValueCollection dict = new TwitterClient().GenerateTokenUrl(ConsumerKey, ConsumerSecret, "https://" + UrlPath + "/Account/TwitterRegistrationCallback");
        // set a session var so we can use it when twitter calls us back
        Session["dict"] = dict;
        // call "authenticate" not "authorize" as the twitter docs say so the user doesn't have to reauthorize the app everytime
        return Redirect("https://api.twitter.com/oauth/authenticate?oauth_token=" + dict["oauth_token"]);
    }

在回调之后,我调用twitter api以获取同样有效的用户数据

[AllowAnonymous]
    public ActionResult TwitterRegistrationCallback(string oauth_token, string oauth_verifier)
    {
        TwitterClient twitterClient = new TwitterClient();
        NameValueCollection dict = (NameValueCollection)Session["dict"];
        NameValueCollection UserDictionary = HttpUtility.ParseQueryString(twitterClient.GetAccessToken(ConsumerKey, ConsumerSecret, oauth_token, oauth_verifier, dict));
        TwitterUserModel twitterUser = JsonConvert.DeserializeObject<TwitterUserModel>(twitterClient.GetTwitterUser(ConsumerKey, ConsumerSecret, UserDictionary));
        Session["twitterUser"] = twitterUser;

        // Returning challenge not working just redirecting to the action inn case of twitter as we are already authenitcated

        return new ChallengeResult("Twitter", Url.Action("ExternalRegistrationCallback", "Account", null));

    }

但是当我返回Challange结果并最终调用

   context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);

以下是我的例外情况(与原始问题相同)

这是未被调用的回调

  // GET: /Account/ExternalRegistrationCallback
    [AllowAnonymous]
    public async Task<ActionResult> ExternalRegistrationCallback()
    {
        //TODO: Check
        if (User.Identity.IsAuthenticated)
        {
            return RedirectToAction("Index", "Manage");
        }

        var loginInfo = await _authenticationManager.GetExternalLoginInfoAsync();


        if (Session["twitterUser"] != null)
        {
            //Workarround for twitter registration callback not using the challenge

            loginInfo = new ExternalLoginInfo();
            TwitterUserModel twitterUser = (TwitterUserModel)Session["twitterUser"];
            loginInfo.Email = twitterUser.email;
        }

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


        // Get the information about the user from the external login provider
        var info = await _authenticationManager.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return View("ExternalLoginFailure");
        }

        // 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:
                //User is already registered We show error and tell the user to go back to login page?
                return RedirectToLocal((string)Session["ReturnUrl"]);
            case SignInStatus.LockedOut:
                return View("Lockout");
            case SignInStatus.RequiresVerification:
                //
                return RedirectToAction("SendCode", new { ReturnUrl = (string)Session["ReturnUrl"], RememberMe = false });
            case SignInStatus.Failure:
            default:
                // User is authenticated through the previous challange, So here needs to be saved

                RegistrationBasicViewModel model = (RegistrationBasicViewModel)Session["RegistrationModel"];

                //Check the user is in our db?
                ApplicationUser user = _userManager.FindByEmail(loginInfo.Email);
                IdentityResult identityResult;
                if (user == null)
                {

                    user = new ApplicationUser
                    {
                        UserName = loginInfo.Email,
                        Email = loginInfo.Email,
                        FirstName = model.FirstName,
                        LastName = model.LastName,
                        Nickname = model.Nickname
                    };
                    identityResult = await _userManager.CreateAsync(user);
                }
                else
                {
                    //TODO : Here we might want to tell the user it already exists
                    identityResult = IdentityResult.Success;

                        //IdentityResult.Failed(new string[] { "User already registered" });
                }

                if (identityResult.Succeeded)
                {

                    identityResult = await _userManager.AddLoginAsync(user.Id, info.Login);
                    if (identityResult.Succeeded)
                    {
                        //Adding the branch after te user is sucessfully added
                        await _signInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

                        _userBranchService.AddUserBranch(user.Id, model.BranchId);

                        //Redirect to home page
                        return RedirectToLocal((string)Session["ReturnUrl"]);
                    }
                }

                setPartnerBranchViewBag(model.PartnerId, (string) Session["partner"]);

                AddErrors(identityResult);
                return View("Register", model );



        }
    }

Twitter config

[HttpRequestException: Response status code does not indicate success: 403 (Forbidden).]
   System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() +223
   Microsoft.Owin.Security.Twitter.<ObtainRequestTokenAsync>d__23.MoveNext(

2 个答案:

答案 0 :(得分:2)

显然Owin使用默认网址(而不是Challange上设置的网址)

默认URL是/ signin-twitter,所以在我的情况下,我必须将https://localhost:44378/signin-twitter配置为twitter应用程序门户中的回调URL之一

答案 1 :(得分:1)

即使将/ signin-twitter添加到我的回调URL中,我仍收到“响应状态代码不表示成功:403(禁止)”。错误。

[HttpRequestException: Response status code does not indicate success: 403 (Forbidden).]
System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() +121662
Microsoft.Owin.Security.Twitter.<ObtainRequestTokenAsync>d__23.MoveNext() +2389
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +31
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +60
Microsoft.Owin.Security.Twitter.<ApplyResponseChallengeAsync>d__12.MoveNext() +1091

即使使用默认设置,也会从Asp.NET MVC模板中立即抛出此异常。