ASP.Net:混合身份验证 Azure AD / 表单

时间:2021-04-14 16:19:58

标签: asp.net-mvc authentication azure-active-directory

我有一个使用表单身份验证的旧版 Asp.Net/MVC/Razor WebApp。

现在,因为有些用户有 Azure AD 帐户,所以我添加了一个特殊的 AD 登录按钮以及通常的代码以使其工作

app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {...})

使用按钮登录后,我在 URL 中输入了以下内容:

https://localhost:44361/Account/Index?ReturnUrl=%2fAccount%2fSignIn

因此在我的 Web.config 中我注释掉了:

<!--<authentication mode="Forms">
  <forms loginUrl="~/Account/Index" timeout="2880" cookieless="UseDeviceProfile" />
</authentication>-->

在这个阶段Azure AD 身份验证工作正常!但是这样做,我破坏了原来的表单身份验证:-(

打电话

 FormsAuthentication.SetAuthCookie(email, false);

还不够:只要我调用控制器,我仍然会重定向到 Azure AD 登录页面

[System.Web.Mvc.Authorize]

另外我收到错误消息是因为

 @Html.AntiForgeryToken()
<块引用>

类型声明 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' 要么 'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider' 不存在于提供的 ClaimsIdentity 中。启用防伪 令牌支持基于声明的身份验证,请验证 配置的声明提供程序在 它生成的 ClaimsIdentity 实例。如果配置的声明 提供者改为使用不同的声明类型作为唯一标识符, 可以通过设置静态属性来配置 AntiForgeryConfig.UniqueClaimTypeIdentifier。

有人可以告诉我如何结合两种身份验证方法吗? 谢谢!

1 个答案:

答案 0 :(得分:0)

这是启动的答案:

    public void ConfigureAuth(IAppBuilder app)
    {
        PublicClientId = "self";

        app.UseCookieAuthentication(new CookieAuthenticationOptions
                                    {
                                            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                                            LoginPath = new PathString("/Account/Index/"),
                                            CookieSecure = CookieSecureOption.Always
                                    });

        app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
                                 {
                                         TokenEndpointPath = new PathString("/Token"),
                                         Provider = new ApplicationOAuthProvider(new StatelessRepository(new DataAccessHelper()), PublicClientId),
                                         RefreshTokenProvider = new AuthenticationTokenProvider
                                                                {
                                                                        OnCreate = CreateRefreshToken,
                                                                        OnReceive = RecieveRefreshToken
                                                                },
                                         AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                                         AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
                                         AllowInsecureHttp = true
                                 });

        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                        ClientId = clientId,
                        Authority = authority,
                        RedirectUri = redirectUri,
                        PostLogoutRedirectUri = redirectUri,
                        Scope = OpenIdConnectScope.OpenIdProfile,
                        ResponseType = OpenIdConnectResponseType.CodeIdToken,
                        TokenValidationParameters = new TokenValidationParameters
                                                    {
                                                            ValidateIssuer = true,
                                                            ValidIssuer = $"https://login.microsoftonline.com/{tenant}/v2.0",
                                                            RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
                                                            NameClaimType = "name",
                                                    },
                        Notifications = new OpenIdConnectAuthenticationNotifications
                                        {
                                                AuthenticationFailed = OnAuthenticationFailed,
                                                SecurityTokenValidated = OnAuthenticationSuccessded
                                        }
                }
        );
    }

在 Web.config 中

<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.8" />
<httpRuntime targetFramework="4.8" />
</system.web>
      <system.webServer>
        <modules>
          <remove name="FormsAuthentication" />
        </modules>
      </system.webServer>

最后在控制器中,验证用户凭据后:

List<Claim> claims = new List<Claim>
                             {
                                     new Claim(ClaimTypes.Name, partnerUser.Email),
                                     new Claim(ClaimTypes.Email, partnerUser.Email),
                                     new Claim(ClaimTypes.NameIdentifier, partnerUser.Email)
                             };
        ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims,
                DefaultAuthenticationTypes.ApplicationCookie);

        Request.GetOwinContext().Authentication.SignIn(claimsIdentity);

加上一个 SignOut 方法:

    public void SignOut()
    {
        IAuthenticationManager authenticationManager = HttpContext.GetOwinContext().Authentication;

        foreach (ClaimsIdentity claimsIdentity in authenticationManager.User.Identities)
        {
            switch (claimsIdentity.AuthenticationType)
            {
                case DefaultAuthenticationTypes.ApplicationCookie:
                    authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
                    break;

                case CookieAuthenticationDefaults.AuthenticationType:
                    authenticationManager.SignOut(
                            OpenIdConnectAuthenticationDefaults.AuthenticationType,
                            CookieAuthenticationDefaults.AuthenticationType);
                    break;
            }
        }

        Session.Abandon();
        Session.RemoveAll();
    }

最后,这是 Global.asax 的一些内容:

    protected void Application_Start()
    {
        AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
        ...           
    }