c# - ¿Por qué mi ClaimsIdentity IsAuthenticated es siempre falsa(para el filtro Authorize de la API web)?
asp.net asp.net-web-api (2)
El problema es debido a un cambio de rotura en .Net 4.5. Como se explica en este artículo , la simple construcción de una identidad de reclamo ya no hace que se autentique devuelva verdadero. En cambio, debe pasar alguna cadena (no importa qué) en el constructor.
Entonces esta línea en el código de arriba:
var claimsIdentity = new ClaimsIdentity( claims );
Se convierte en esto:
// exact string doesn''t matter
var claimsIdentity = new ClaimsIdentity( claims, "CustomApiKeyAuth" );
Y el problema está resuelto. Actualización: ver otra respuesta de Leo. El valor exacto de AuthenticationType puede o no ser importante dependiendo de qué más tenga en su auth pipeline.
Actualización 2: como sugirió Robin van der Knaap en los comentarios, uno de los valores de System.Security.Claims.AuthenticationTypes
podría ser apropiado.
var claimsIdentity = new ClaimsIdentity( claims, AuthenticationTypes.Password );
// and elsewhere in your application...
if (User.Identity.AuthenticationType == AuthenticationTypes.Password) {
// ...
}
En un proyecto de API web, estoy anulando el proceso de autenticación normal para verificar los tokens. El código se ve así:
if ( true ) // validate the token or whatever here
{
var claims = new List<Claim>();
claims.Add( new Claim( ClaimTypes.Name, "MyUser" ) );
claims.Add( new Claim( ClaimTypes.NameIdentifier, "MyUserID" ) );
claims.Add( new Claim( ClaimTypes.Role, "MyRole" ) );
var claimsIdentity = new ClaimsIdentity( claims );
var principal = new ClaimsPrincipal( new[] { claimsIdentity } );
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
}
Y luego, cuando aplique el atributo [Authorize]
a un controlador, no se autoriza.
El código de depuración confirma el mismo comportamiento:
// ALWAYS FALSE!
if ( HttpContext.Current.User.Identity.IsAuthenticated ) {
// do something
}
¿Por qué cree que el usuario no está autenticado a pesar de que he construido un ClaimsIdentity válido y lo he asignado al hilo?
Si bien la respuesta provista tiene cierta validez, no es del todo correcta. No puede suponer que simplemente agregar cualquier cadena funcionará mágicamente. Como se indica en uno de los comentarios, esta cadena debe coincidir con una enumeración de AuthenticationTypes
que a su vez debe coincidir con la especificada en el middleware OWIN authentication / authorization ... por ejemplo ...
public void ConfigureOAuth(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
OAuthAuthorizationServerOptions serverOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new Microsoft.Owin.PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
AuthenticationType = AuthenticationTypes.Password,
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
Provider = new AppAuthServerProvider()
};
app.UseOAuthAuthorizationServer(serverOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
AuthenticationType = AuthenticationTypes.Password
});
}
Sin embargo, en el escenario anterior no importaría mucho. Pero, si usa más niveles de autenticación / autorización, los reclamos se asociarán al que coincida con el mismo AuthenticationType
... otro ejemplo es cuando usa autenticación de cookies ...
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/auth/login")
});
}
donde AuthenticationType
describe el nombre de la cookie, dado que su aplicación puede haber obtenido otras cookies de otros proveedores, es importante que configure AuthenticationType
al crear instancias de las reclamaciones para asociarlas luego a la cookie correcta.