社交注销不与OpenIdConnect一起使用

时间:2017-11-15 17:01:55

标签: asp.net-mvc authentication oauth owin

我使用OpenIdConnect身份验证(用于Azure身份验证)和Google,Facebook和Microsoft帐户的身份验证提供程序创建了一个MVC Web应用程序。

StartupAuth中的配置如下所示:

    public void ConfigureAuth(IAppBuilder app)
    {
        if (Config.TaskboardUserSource == Config.DirectoryService.AzureAD)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                ExpireTimeSpan = new TimeSpan(6, 0, 0),
                SlidingExpiration = true,

                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Home/Index"),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });

    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);


    app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
                    app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = Config.ClientId,
                    Authority = string.Format("{0}common", Config.AadInstance),
                    UseTokenLifetime = false,
                    TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = false,
                    },
                    Notifications = new OpenIdConnectAuthenticationNotifications()
                    {
                        SecurityTokenValidated = (context) =>
                        {
                            return Task.FromResult(0);
                        },
                        AuthorizationCodeReceived = (context) =>
                        {
                            var code = context.Code;

                            ClientCredential credential = new ClientCredential(Config.ClientId, Config.AppKey);
                            string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                            string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                            AuthenticationContext authContext = new AuthenticationContext(string.Format("{0}{1}", Config.AadInstance, tenantID), new ADALTokenCache(signedInUserID));
                            AuthenticationResult result = authContext.AcquireTokenByAuthorizationCodeAsync(
                                code,
                                new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
                                credential,
                                Config.GraphResourceID).Result;

                            return Task.FromResult(0);
                        },

                        RedirectToIdentityProvider = (context) =>
                        {
                            // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                            // this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
                            // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                            string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                            context.ProtocolMessage.RedirectUri = appBaseUrl + "/";
                            context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;

                            return Task.FromResult(0);
                        },


                        AuthenticationFailed = (context) =>
                        {
                            context.OwinContext.Response.Redirect("/Home/Index");
                            context.HandleResponse(); // Suppress the exception
                            return Task.FromResult(0);
                        }
                    }
                });

            var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
            {
                AppId = Config.FBAppId,
                AppSecret = Config.FBAppSecret,
                UserInformationEndpoint = Config.FBUserInformationEndpoint

            };
            facebookAuthenticationOptions.Scope.Add("email");
            app.UseFacebookAuthentication(facebookAuthenticationOptions);

            app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
            {
                ClientId = Config.GoogleClientId,
                ClientSecret = Config.GoogleClientSecret
            });

            var microsoftOptions = new MicrosoftAccountAuthenticationOptions()
            {
                ClientId = Config.MSAppId,
                ClientSecret = Config.MSAppSecret,
            };
            microsoftOptions.Scope.Add("wl.basic");
            microsoftOptions.Scope.Add("wl.emails");
            app.UseMicrosoftAccountAuthentication(microsoftOptions);
        }
    }

所有身份验证选项均可正常运行。

当我想注销时,唯一可以注销的是OpenIdConnect Signout。 对于所有其他身份验证提供程序,cookie仍然可用,只需单击“登录”按钮即可显示安全页面,而无需输入密码。

My Signout看起来像这样:

    public void SignOut()
    {
        string callbackUrl = Url.Action("SignOutCallback", "Account", routeValues: null, protocol: Request.Url.Scheme);
        HttpContext.GetOwinContext().Authentication.SignOut(
             new AuthenticationProperties { RedirectUri = callbackUrl },
            HttpContext.GetOwinContext()
                       .Authentication.GetAuthenticationTypes()
                       .Select(o => o.AuthenticationType).ToArray());
        HttpContext.GetOwinContext().Authentication.SignOut(
            new AuthenticationProperties { RedirectUri = callbackUrl },
            CookieAuthenticationDefaults.AuthenticationType);
    }

如何确保用户已退出并重定向到起始页?

1 个答案:

答案 0 :(得分:0)

在我的注销代码中插入switch case语句后,为每个logonprovider执行注销后,它终于可以工作了。这是我的代码:

 public async Task<ActionResult> SignOut()
    {
        var currentUser = await UserService.CurrentUser();
        if (currentUser != null)
        {
            var redirectUrl = Request.GetBaseUrl();
            var loginProviders = new string[] {
                        "Google",
                        "TwoFactorRememberBrowser",
                        "TwoFactorCookie",
                        "ExternalCookie",
                        "ApplicationCookie"
                };
            switch (currentUser.LoginProvider)
            {
                case LogonProvider.FacebookProviderKey:
                    {
                        loginProviders = new string[] {
                        "Facebook",
                        "TwoFactorRememberBrowser",
                        "TwoFactorCookie",
                        "ExternalCookie",
                        "ApplicationCookie" };
                        break;
                    }
                case LogonProvider.GoogleProviderKey:
                    {

                        loginProviders = new string[] {
                        "Google",
                        "TwoFactorRememberBrowser",
                        "TwoFactorCookie",
                        "ExternalCookie",
                        "ApplicationCookie" };
                        //return new RedirectResult($"https://www.google.com/accounts/Logout");
                        break;
                    }
                case LogonProvider.MicrosoftProviderKey:
                    {
                        loginProviders = new string[] {
                        "Microsoft",
                        "TwoFactorRememberBrowser",
                        "TwoFactorCookie",
                        "ExternalCookie",
                        "ApplicationCookie" };
                        break;
                    }
                default:
                    {
                        loginProviders = new string[] {
                        "Office365",
                        "TwoFactorRememberBrowser",
                        "TwoFactorCookie",
                        "ExternalCookie",
                        "ApplicationCookie" };
                        break;
                    }
            }

            HttpContext.GetOwinContext().Authentication.SignOut(new AuthenticationProperties { RedirectUri = redirectUrl }, loginProviders);
        }
        return RedirectToAction("Index", "Home");
    }