No han sido pocos los post que tengo en este blog referidos a la gestión de la identidad, desde Zermatt hasta WIF, la identidad y su gestión es uno de los temas que me apasiona y sobre los que siempre me gusta escribir. Este post es una entrada de una serie, que no tengo ni idea de cuanto se extenderá, acerca de los cambios con respecto a este tema en .NET 4.5 y Visual Studio 2012, que espero os resulten tan interesantes como a mi y, sino, por lo menos que os ayuden a entender un poco que hay de nuevo en este tema.
Generic Identity / Principal, de hermanos a padres
La primera nota importante que haremos notar es que todo el trabajo avanzado con Windows Identity Foundation pasa a estar incorporado dentro de .NETer Framework, de tal forma que los conceptos de Claims y todo lo relacionado con ello, iremos poco a poco, lo tendremos ahora en los namespaces System.Security y System.IdentityModel. Por supuesto, este trabajo no ha estado fuera de un necesario rediseño de ciertos elementos del API de .NET Framework. Uno de estos elementos tiene que ver con la jerarquía de IIdentity y IPrincipal. Hasta ahora, las distintas implementaciones que teníamos, Generic Identity/Principal, Windows Identity / Principal y Claims Identity / Principal eran hermandos. En la nueva versión del framework, con todo el sentido del mundo, esto ya no es así, puesto que tanto Generic Identity / Principal como Windows Identity / Principal son hijos de Claims Identity / Principal, es decir, todo en la gestión de la identidad en .NET son Claims. Con el fin de poner un ejemplo podríamos ejecutar las siguientes pieza de código, que funcionarían perfectamente en .NET 4.5 y gracias a la cuales podríamos ver cuales son las claims de una identidad windows o una identidad genérica.
1 |
<span style="color: #008000">//create current windows principal</span> |
1 |
var windowsPrincipal = <span style="color: #0000ff">new</span> WindowsPrincipal(WindowsIdentity.GetCurrent()); |
1 |
  |
1 |
<span style="color: #008000">//show claims</span> |
1 |
  |
1 |
var claimsPrincipal = windowsPrincipal <span style="color: #0000ff">as</span> ClaimsPrincipal; |
1 |
  |
1 |
<span style="color: #0000ff">foreach</span> (var claim <span style="color: #0000ff">in</span> claimsPrincipal.Claims) |
1 |
Dump(claim); |
Cada uno de los atributos de una identidad Windows ha sido traducido a sus correspondientes claims, cuyos tipos podemos ver en las constantes definidas por el tipo ClaimTypes. Este mismo código, funcionaría también perfectamente si trabajaramos con Generic Identity / Principal como puede ver a continuación.
1 |
<span style="color: #008000">//create generic principal</span> |
1 |
var genericIdentity = <span style="color: #0000ff">new</span> GenericIdentity(<span style="color: #006080">"Unai"</span>); |
1 |
var genericPrincipal = <span style="color: #0000ff">new</span> GenericPrincipal(genericIdentity, <span style="color: #0000ff">new</span> <span style="color: #0000ff">string</span>[] { <span style="color: #006080">"Admin"</span> }); |
1 |
  |
1 |
<span style="color: #008000">//dump claims</span> |
1 |
var claimsPrincipal = genericPrincipal <span style="color: #0000ff">as</span> ClaimsPrincipal; |
1 |
<span style="color: #0000ff">foreach</span> (var claim <span style="color: #0000ff">in</span> claimsPrincipal.Claims) |
1 |
Dump(claim); |
Los mecanismos de comprobación de identidad y rol tradicionales como IIdentity.Name y IIdentity.IsInRole seguirán funcionando correctamente, aunque en este caso, se basarán en la búsqueda y tratamiento de los claims de cada una de las identidades, por ello IClaimsIdentity define las constantes de los tipos de claims en los que se basará la búsqueda del nombre y/o comprobación del rol.
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> DefaultIssuer = <span style="color: #006080">"LOCAL AUTHORITY"</span>; |
1 |
  |
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> DefaultNameClaimType = <span style="color: #006080">"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"</span>; |
1 |
  |
1 |
<span style="color: #0000ff">public</span> <span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> DefaultRoleClaimType = <span style="color: #006080">"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"</span>; |
Una cosa chula y curiosa es que cuando creamos nuestra identidad basándonos en ClaimsIdentity podemos decidir que tipos de claims serán los utilizados para estas comprobaciones, tal y como podemos ver en el siguiente ejemplo con la sobrecarga del constructor ClaimsIdentity
1 |
<span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> NAME_TYPE = <span style="color: #006080">"http://www.plainconcepts/claims/types/customNameType"</span>; |
1 |
<span style="color: #0000ff">const</span> <span style="color: #0000ff">string</span> ROLE_TYPE = <span style="color: #006080">"http://www.plainconcepts/claims/types/customRoleType"</span>; |
1 |
  |
1 |
var claims = <span style="color: #0000ff">new</span> List<Claim>() |
1 |
{ |
1 |
<span style="color: #0000ff">new</span> Claim(NAME_TYPE,<span style="color: #006080">"Unai"</span>), |
1 |
<span style="color: #0000ff">new</span> Claim(ROLE_TYPE,<span style="color: #006080">"SuperAdmin"</span>), |
1 |
<span style="color: #0000ff">new</span> Claim(ClaimTypes.Name,<span style="color: #006080">"Maria"</span>), |
1 |
<span style="color: #0000ff">new</span> Claim(ClaimTypes.Role,<span style="color: #006080">"Admin"</span>), |
1 |
}; |
1 |
var claimsIdentity = <span style="color: #0000ff">new</span> ClaimsIdentity(claims,<span style="color: #006080">"AUTH_TYPE"</span>, NAME_TYPE, ROLE_TYPE); |
1 |
var claimsPrincipal = <span style="color: #0000ff">new</span> ClaimsPrincipal(claimsIdentity); |
1 |
  |
1 |
var isInRole = claimsPrincipal.IsInRole(<span style="color: #006080">"SuperAdmin"</span>); <span style="color: #008000">// isInRole is true</span> |
1 |
var name = claimsPrincipal.Identity.Name; <span style="color: #008000">// name is Unai</span> |
No obstante, ahora que sabemos que todo son Claims, realmente el código tipo Name/IsInRole ya no es necesario (solamente por compatibilidad hacia atrás que es por lo que se ha dejado) puesto que lo único que tenemos que hacer es preguntarnos si alguna claim existe gracias a los distintos métodos que ClaimsPrincipal nos da como HasClaim, FindFirst o FindAll.
Bueno, hasta aquí hemos llegado con la primera entrada para abrir un poco el hambre de saber más, en la siguiente entrada trataremos la gestión de la identidad en un entorno web, hablando sobre los cambios en .NET 4.5 y algunos elementos que teneos que tener claros.
Saludos
Unai
En la anterior entrega hablamos sobre como Claims Identity / Principal pasaban a ser elementos fundamentales