Я пытаюсь реализовать твиттер вход / вверх. В веб-приложении asp.net, но я получаю статус 403 http при последнем обратном вызове.
У меня настроены URL-адреса для обратных вызовов на портале приложений в Твиттере (я думаю, что они правильные)
Я даю немного контекста о том, что я пытаюсь сделать
- Перенаправить пользователя в твиттер sining
- Затем выполняется первый обратный вызов (здесь нет проблем), и я вызываю твиттер-API, чтобы получить информацию о пользователе.
- После получения сведений о пользователе я возвращаю результат запроса, чтобы я мог получить идентификатор пользователя, и для этого я указываю второй обратный вызов
Второй обратный вызов не выполняется.
Может кто-нибудь указать мне, что я делаю не так? Или как я могу отладить проблему?
Мне известно, что твиттер проверяет, что URL-адрес обратного вызова должен быть установлен на портале для разработчиков приложений. Я получил это из этого вопроса вопрос
Вот мой код и конфиг
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 CA
"B13EC36903F8BF4701D498261A0802EF63642BC3" // DigiCert High Assurance EV Root CA
}),
});
Вызов входа в твиттер (я указываю первый 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"]);
}
После обратного вызова я вызываю твиттер-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(