我正在玩Owin.Security.Providers
项目以允许我的MVC 5应用程序使用各种社交网络登录。我在LinkedIn中创建了一个应用,并将其范围设置为r_emailaddress
和r_basicprofile
。当我尝试使用LinkedIn accout登录时,我的返回网址上会显示/Login/SigninRedirect?error=access_denied
。虽然我设置为CallbackPath
网址的/signin-redirect
具有code
和state
属性。在Fiddler中,它看起来像这样:/signin-redirect?code=<code_id>&state=<state_id>
。
任何人都有任何想法我可能做错了什么?
这是我的代码:
protected virtual void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
var linkedInAuthOptions = new LinkedInAuthenticationOptions()
{
ClientId = <client_id>,
ClientSecret = <client_secret>,
CallbackPath = new PathString("/signin-redirect")
};
app.UseLinkedInAuthentication(linkedInAuthOptions);
}
在我的登录控制器中,我处理登录和重定向类似于VS2013示例:
public class LoginController : Controller
{
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
var redirectUrl = "/Login/SigninRedirect";
redirectUrl += string.IsNullOrEmpty(returnUrl) ? "" : "?redirectUrl=" + returnUrl;
return new ChallengeResult(provider, redirectUrl);
}
// Redirects from successful social signin to a speccified URL.
public ActionResult SigninRedirect(string redirectUrl)
{
var redirect = string.IsNullOrEmpty(redirectUrl) ? "/" : redirectUrl;
ExternalLoginInfo loginInfo = AuthenticationManager.GetExternalLoginInfo();
// loginInfo is null when trying to sign in with LinkedIn
// works fine for Twitter though
if (loginInfo != null)
{
var authResult = AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie).Result;
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var claims = authResult.Identity.Claims.ToList();
claims.Add(new Claim(ClaimTypes.AuthenticationMethod, loginInfo.Login.LoginProvider));
var claimsIdentity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ExternalCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = true }, claimsIdentity);
}
return new RedirectResult(redirect);
}
#region Helpers
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
private class ChallengeResult : HttpUnauthorizedResult
{
private const string XsrfKey = "XsrfId";
public ChallengeResult(string provider, string redirectUrl, string userId = null)
{
LoginProvider = provider;
RedirectUrl = redirectUrl;
UserId = userId;
}
public string UserId { get; set; }
public string RedirectUrl { get; set; }
public string LoginProvider { get; set; }
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties() {RedirectUri = RedirectUrl};
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}
#endregion
}
当我尝试使用Twitter帐户登录时,相同的代码工作正常。
答案 0 :(得分:1)
发现了这个问题。问题是我为Twitter和LinkedIn提供商注册了相同的CallbackPath
(/signin-redirect
)。像这样:
var twitterAuthOptions = new TwitterAuthenticationOptions()
{
ConsumerKey = <consumerKey>,
ConsumerSecret = <consumerSecret>,
CallbackPath = new PathString("/signin-redirect")
};
app.UseTwitterAuthentication(twitterAuthOptions);
var linkedInAuthOptions = new LinkedInAuthenticationOptions()
{
ClientId = <clientId>,
ClientSecret = <clientSecret>,
CallbackPath = new PathString("/signin-redirect")
};
app.UseLinkedInAuthentication(linkedInAuthOptions);
当我设置不同的CallbackPath
时,一切都开始正常。