我正在尝试将POC从现有MVC 4应用程序中的表单身份验证切换到基于声明的应用程序,但无法使自定义授权属性工作 - 由于总cookie大小而导致无限重定向循环以已知的“错误请求”问题结束... 原因 - 尽管我在SecurityTokenValidated处理程序中看到成功创建了具有预期声明集合的标识,但我在调试中看到它在属性上下文中没有经过身份验证的身份(以及正确的声明集合)。
因此,在OIDC中间件处理之后,它似乎在某种程度上丢失,并且在属性上下文中不可用,因此我无法进一步检查“角色”声明。
也许我错过了什么?
我的OWIN初创公司:
AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
//AuthenticationMode = AuthenticationMode.Active, // ? https://github.com/IdentityServer/IdentityServer3/issues/1963
Authority = OAuthServerUrl,
ClientId = "my_app",
RedirectUri = MyAppUrl,
ResponseType = "id_token token", //notice, if response type 'token' is requested, IdentityServer stops including the claims in the identity token, though we could set alwaysInclude=true for some scope claims (ex. for role)
Scope = "openid profile roles",
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
PostLogoutRedirectUri = MyAppUrl,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n =>
{
var id = n.AuthenticationTicket.Identity;
//n.OwinContext.Authentication.SignIn(id);
//tried SignIn() explicitly, and even setting HttpContext.Current.User and Thread.CurrentPrincipal to n.AuthenticationTicket.Identity, but without luck
return Task.FromResult(0);
},
RedirectToIdentityProvider = async n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var result =
await n.OwinContext.Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType);
var idToken = result?.Identity.Claims.GetValue("id_token");
if (idToken != null)
{
n.ProtocolMessage.IdTokenHint = idToken;
}
}
await Task.FromResult(0);
}
}
});
我的自定义属性继承自System.Web.Mvc.AuthorizeAttribute:
public class ClaimsAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//var owinContext = HttpContext.Current.GetOwinContext();
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// 403 we know who you are, but you haven't been granted access
filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Forbidden);
}
else
{
// 401 who are you? go login and then try again
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
其中filterContext.HttpContext.User.Identity(也尝试过HttpContext.Current.User和Thread.CurrentPrincipal)具有来自LOCAL AUTHORITY颁发者的单一“名称”声明的声明集合(默认值为?)。 我还修改了Web.config来禁用表单auth:
<authentication mode="None">
...
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="999" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="3" passwordStrengthRegularExpression="" applicationName="Audit" />
<!--<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="999" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="3" passwordStrengthRegularExpression="" applicationName="Audit" />-->
</providers>
</membership>
<profile>
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" applicationName="Audit" />
<!--<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" applicationName="Audit" />-->
</providers>
</profile>
<roleManager enabled="true">
<roleManager enabled="false">
<providers>
<clear />
<add connectionStringName="ApplicationServices" applicationName="Audit" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<add applicationName="Audit" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<!--<add connectionStringName="ApplicationServices" applicationName="Audit" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />-->
<!--<add applicationName="MyApp" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />-->
</providers>
</roleManager>
...
<handlers>
<remove name="FormsAuthentication" />
<remove name="RoleManager" />
更新1:我已经将应用程序从MVC 4迁移到最新的MVC 5,希望它是与MVC 4相关的问题,但不幸的是,没有区别。显然,我的客户端应用程序/配置有问题。