ASP.Net:混合身份验证Azure AD/表单
我有一个使用表单身份验证的旧版 Asp.Net/MVC/Razor WebApp.
I've got a legacy Asp.Net/MVC/Razor WebApp that uses Forms authentication.
现在,由于某些用户拥有一个Azure AD帐户,我添加了一个特殊的AD登录按钮以及使之正常运行的常用代码
Now, because some users have an Azure AD account, I added a special AD SignIn button plus the usual code to make it work
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{...})
使用按钮登录后,我进入了URL:
After the sign in using the button, I was getting in the following in the URL:
https://localhost:44361/Account/Index?ReturnUrl=%2fAccount%2fSignIn
因此,在我的Web.config中,我注释掉了:
Therefore in my Web.config I commented out:
<!--<authentication mode="Forms">
<forms loginUrl="~/Account/Index" timeout="2880" cookieless="UseDeviceProfile" />
</authentication>-->
在此阶段, Azure AD身份验证可以正常工作!但是这样做,我破坏了原始的 Forms 身份验证:-(
At this stage Azure AD authentication works fine! But doing so, I broke the original Forms authentication :-(
只需打电话
FormsAuthentication.SetAuthCookie(email, false);
还不够:我使用
[System.Web.Mvc.Authorize]
此外,由于以下原因,我收到了错误消息
Plus I'm getting error messages because of
@Html.AntiForgeryToken()
类型的声明'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'或者'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider'在提供的ClaimsIdentity上不存在.启用防伪令牌支持以及基于声明的身份验证,请验证配置的声明提供程序会在它生成的ClaimsIdentity实例.如果已配置声明提供者而是使用其他声明类型作为唯一标识符,可以通过设置static属性进行配置AntiForgeryConfig.UniqueClaimTypeIdentifier.
A claim of type 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' or 'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider' was not present on the provided ClaimsIdentity. To enable anti-forgery token support with claims-based authentication, please verify that the configured claims provider is providing both of these claims on the ClaimsIdentity instances it generates. If the configured claims provider instead uses a different claim type as a unique identifier, it can be configured by setting the static property AntiForgeryConfig.UniqueClaimTypeIdentifier.
有人可以告诉我如何结合两种身份验证方法吗?谢谢!
Can someone please tell me how to combine both authentication methods? Thank you!
以下是启动的答案:
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中
Here in the 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>
最后,在验证用户凭据之后,在控制器中的此处:
And finally here in the controller, after validating the user credentials:
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方法:
Plus a SignOut method:
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的一些东西:
And finally, here is something for the Global.asax:
protected void Application_Start()
{
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
...
}