【问题标题】:Adding Scope, "wl.emails", to MicrosoftAccountAuthenticationOptions in Startup.Auth.cs causes issues在 Startup.Auth.cs 中将范围“wl.emails”添加到 MicrosoftAccountAuthenticationOptions 会导致问题
【发布时间】:2013-12-05 16:11:14
【问题描述】:

请告诉我出了什么问题。

    public void ConfigureAuth(IAppBuilder app)
    {
        var mo = new MicrosoftAccountAuthenticationOptions();
        mo.ClientId = "xxxxxxxxxxxxxxxxx";
        mo.ClientSecret = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
        mo.Scope.Add("wl.basic"); // No effect if this commented out
        mo.Scope.Add("wl.emails");

        // IF I COMMENT NEXT TWO PROPERTIES, USER IS AUTHENTICATED, BUT THE DB IS NOT
        // UPDATED. LEAVE THEM AND THE REDIRECT FROM MSLIVE ENDS ON LOGIN PAGE

        mo.SignInAsAuthenticationType = "External";
        mo.Provider = new MicrosoftAccountAuthenticationProvider()
        {
            OnAuthenticated = (context) =>
                {
         // Set breakpoint here to see the context.Identity.Claims HAS CLAIMS DESIRED.
         // SO IT APPEARS TO ME Nothing to do here but verify they exist in the debugger.
         //(context.Identity.Claims).Items  ARE:  
         //{http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: xxxxxxxxx}
         //{http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: yyyy yyyyy} 
         //{urn:microsoftaccount:id: xxxxxxxx}  
         //{urn:microsoftaccount:name: yyyy yyyyy}  
         //{http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: xxxxxxxx@hotmail.com}
                return Task.FromResult(0);
                }
        };
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login")
        });
        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        app.UseMicrosoftAccountAuthentication(mo);
    }

一个合理的期望断言框架将透明地处理将范围添加到默认*AuthenticationOptions。随后,编写MVC5模板,开发人员can extract and persist ClaimsExternalLoginConfirmation代码中。另一个合理的预期是框架会将传入的标准 ClaimTypes 转换为框架公开的ClaimsIdentity 中的声明。

我很高兴源代码可用MicrosoftAccountAutheticationHandler.cs,我会检查它来解决这个问题;缺乏回应。随着文档和框架的成熟,向 Katana 致以最良好的祝愿。该框架有没有办法帮助开发人员发现配置问题?

【问题讨论】:

    标签: visual-studio-2013 claims-based-identity asp.net-mvc-5 asp.net-identity owin


    【解决方案1】:

    如果我们都没有碰到同样的推理逻辑砖墙,我会同意你的...... 我认为这与分离的 Owin 安全上下文有关,而 Web 应用程序在单独的上下文中运行,您必须“播种”网络。所以我的推断是这样的:

    在 Startup.Auth.cs 中

    var microsoftOptions =
                new Microsoft.Owin.Security.MicrosoftAccount.MicrosoftAccountAuthenticationOptions
                {
                    CallbackPath = new Microsoft.Owin.PathString("/Callbacks/External"),//register at oAuth provider
                    ClientId = "xxxx",
                    ClientSecret = "yyyyyyyyyyyyyyyyy",
                    Provider = new Microsoft.Owin.Security.MicrosoftAccount.MicrosoftAccountAuthenticationProvider
                    {
                        OnAuthenticated = (context) =>
                            {
                                context.Identity.AddClaim(new Claim(providerKey, context.Identity.AuthenticationType));
                                context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirstValue(ClaimTypes.Name)));
                                return System.Threading.Tasks.Task.FromResult(0);
                            }
                    }
                };
            microsoftOptions.Scope.Add("wl.basic");
            microsoftOptions.Scope.Add("wl.emails");
            app.UseMicrosoftAccountAuthentication(microsoftOptions);
    

    在 AccountController 中:

        [AllowAnonymous]
        public async Task<ActionResult> oAuthCallback(string returnUrl)
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            if (loginInfo == null)
            {
                if (User.Identity.IsAuthenticated)
                    return RedirectToAction("Index", "Manage");
                else
                    return RedirectToAction("Login");
            }
    
            var currentUser = await UserManager.FindAsync(loginInfo.Login);
            if (currentUser != null)
            {
                await StoreExternalTokensOnLocalContext(currentUser);
            }
            //.... rest as same as per AspNet Sample project.
        }
    
    
        private async Task StoreExternalTokensOnLocalContext(ApplicationUser user)
        {
            if (user == null)
                return;
    
            var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
            if (externalIdentity != null)
            {
                // Retrieve the existing claims for the user and add the FacebookAccessTokenClaim 
                var currentClaims = await UserManager.GetClaimsAsync(user.Id);
                //var providerClaim = externalIdentity.FindFirstValue("provider") ?? string.Empty;
                await StoreClaim("provider", user.Id, externalIdentity);
                await StoreClaim("FacebookId", user.Id, externalIdentity);
                await StoreClaim("image", user.Id, externalIdentity);
                await StoreClaim("link", user.Id, externalIdentity);
                await StoreClaim(ClaimTypes.Name, user.Id, externalIdentity);
                await StoreClaim(ClaimTypes.Email, user.Id, externalIdentity);
    
                var addedClaims = await UserManager.GetClaimsAsync(user.Id);
            }
        }
    
        private async Task StoreClaim(string typeName, string userId, ClaimsIdentity externalIdentity)
        {
            var providerClaim = externalIdentity.Claims.FirstOrDefault(c => c.Type.Equals(typeName));
            if (providerClaim == null)
                return;
            var previousClaims = await UserManager.GetClaimsAsync(userId);
            if (previousClaims.IndexOf(providerClaim) >= 0)
                return;
            var idResult = await UserManager.AddClaimAsync(userId, providerClaim);
        }
    

    【讨论】:

      猜你喜欢
      • 2010-12-24
      • 1970-01-01
      • 2011-04-26
      • 2013-08-30
      • 2013-03-10
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多