删除外部帐户后,ASP.net Identity停止分发外部Cookie

时间:2015-04-27 21:50:47

标签: asp.net-mvc asp.net-identity

我的网站设置包含四个第三方登录服务,Microsoft,VS,Github和Linkedin。一切似乎都很好,我可以登录/退出,添加/删除外部帐户没有问题。

然而,它似乎停止了工作。当我尝试使用任何第三方服务登录时,它只会让我回到登录页面。

查看ExternalLoginCallback AuthenticateResult.Identity似乎null并且无法获得外部登录信息。在客户端看它看起来好像从未得到external signin cookie

我仍然无法一致地重现此错误,因此很难确定可能发生的事情。任何帮助都会很棒。

更新1:我能够确定要重现的步骤:

  1. 登录具有多个关联登录的帐户
  2. 删除其中一个登录
  3. 在新的浏览器或私人会话中,尝试使用任何第三方帐户登录,您将在没有外部Cookie的情况下返回登录状态。
  4. 在遇到错误后,它不会将cookie分发给任何新会话,直到IIS重新启动。

    更新2:看起来它与设置Session变量有关。

    removeLogin操作中,我向会话添加了一个值。我不确定为什么,但当我停止这样做时,我就不再有问题了。是时候弄明白为什么...... 更新3:看起来这个问题已经reported to the Katana Team

    更新4:看起来其他人已遇到此问题。 Stackoverflow post。他们没有提供解决它所需的所有代码,因此我将此处作为答案包含在内。

    Startup.Auth.cs

    public void ConfigureAuth(IAppBuilder app) {
    
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(appContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.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,
            AuthenticationMode = AuthenticationMode.Active,
            LoginPath = new PathString("/Login"),
            LogoutPath = new PathString("/Logout"),
            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, User, int>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                    getUserIdCallback: (id) => (Int32.Parse(id.GetUserId()))
                )
            }
        });
        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(new MicrosoftAccountAuthenticationOptions{
            ClientId = ConfigurationManager.AppSettings["MSA:Id"],
            ClientSecret = ConfigurationManager.AppSettings["MSA:Secret"],
            Caption = "Microsoft"
        });
    
        app.UseVisualStudioAuthentication(new VisualStudioAuthenticationOptions(){
            AppId = ConfigurationManager.AppSettings["VSO:Id"],
            AppSecret = ConfigurationManager.AppSettings["VSO:Secret"],
            Provider = new VisualStudioAuthenticationProvider(){
                OnAuthenticated = (context) =>{
                    context.Identity.AddClaim(new Claim("urn:vso:access_token", context.AccessToken, XmlSchemaString, "VisualStudio"));
                    context.Identity.AddClaim(new Claim("urn:vso:refresh_token", context.RefreshToken, XmlSchemaString, "VisualStudio"));
                    return Task.FromResult(0);
                }
            },
            Caption = "Visual Studio"
        });
    
        app.UseGitHubAuthentication(new GitHubAuthenticationOptions{
            ClientId = ConfigurationManager.AppSettings["GH:Id"],
            ClientSecret = ConfigurationManager.AppSettings["GH:Secret"],
            Caption = "Github"
        });
    
        app.UseLinkedInAuthentication(new LinkedInAuthenticationOptions {
            ClientId = ConfigurationManager.AppSettings["LI:Id"],
            ClientSecret = ConfigurationManager.AppSettings["LI:Secret"],
            Caption = "LinkedIn"
        });
    }
    

1 个答案:

答案 0 :(得分:3)

OWIN和asp.net处理cookie /会话的方式不同。如果您在初始化会话之前使用OWIN进行授权,则初始化会话后的任何人都将无法登录。

解决方法:将以下内容添加到Global.asax

// Fix for OWIN session bug
    protected void Application_AcquireRequestState() {
        Session["Workaround"] = 0;
    }
}

长期: OWIN和asp.net处理会话/ cookie的方式将在vNext中合并,在此之前使用解决方法......