authentication - Problemas para completar ClaimsPrincipal cuando se usa EasyAuth para autenticarse contra AAD en Azure App Service en una aplicaciĆ³n web Asp.Net Core
asp.net-core azure-web-sites (5)
El siguiente código descifra el token AAD del encabezado HTTP del Servicio de aplicaciones de Azure y completa HttpContext.User con las notificaciones. Es difícil, ya que desea almacenar en caché la configuración en lugar de buscarla en cada solicitud:
OpenIdConnectConfigurationRetriever r = new OpenIdConnectConfigurationRetriever();
ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.Endpoint, r);
OpenIdConnectConfiguration config = await configManager.GetConfigurationAsync();
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKeys = config.SigningKeys.ToList(),
ValidateIssuer = true,
ValidIssuer = config.Issuer,
ValidateAudience = true,
ValidAudience = options.Audience,
ValidateLifetime = true,
ClockSkew = new TimeSpan(0, 0, 10)
};
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = null;
SecurityToken validToken = null;
string token = context.Request.Headers["X-MS-TOKEN-AAD-ID-TOKEN"];
if (!String.IsNullOrWhiteSpace(token))
{
principal = handler.ValidateToken(token, tokenValidationParameters, out validToken);
var validJwt = validToken as JwtSecurityToken;
if (validJwt == null) { throw new ArgumentException("Invalid JWT"); }
if (principal != null)
{
context.User.AddIdentities(principal.Identities);
}
}
Solo funciona para Azure AD. Para admitir otros proveedores de ID (Facebook, Twitter, etc.), tendría que detectar los encabezados relevantes y descubrir cómo analizar el token de cada proveedor. Sin embargo, solo debería haber variaciones sobre el tema anterior.
Tenemos una aplicación web basada en Asp.Net core. No contiene ningún middleware de autenticación configurado en él.
Estamos hospedando en Azure App Service y utilizando la opción de Autenticación / Autorización (EasyAuth) para autenticar en Azure AD.
La autenticación funciona bien: obtenemos los encabezados necesarios insertados y podemos ver la identidad autenticada en /.auth/me. Pero la propiedad HttpContext.User no se rellena.
¿Es este un problema de compatibilidad para Asp.Net core? ¿O estoy haciendo algo mal?
Escribí un pequeño middleware básico para hacer esto. Creará una identidad basada en el punto final .auth / me. La identidad se crea en la canalización de autenticación para que los atributos y políticas [autorizar] funcionen con la identidad.
Lo puedes encontrar aquí:
https://github.com/lpunderscore/azureappservice-authentication-middleware
o en nuget:
https://www.nuget.org/packages/AzureAppserviceAuthenticationMiddleware/
Una vez agregado, simplemente agregue esta línea a su inicio:
app.UseAzureAppServiceAuthentication ();
He creado un middleware personalizado que completa la propiedad del usuario hasta que el equipo de Azure lo resuelva.
Lee los encabezados de la Autenticación del Servicio de aplicaciones y crea un usuario que será reconocido por
[Authorize]
y tiene un reclamo de
name
.
// Azure app service will send the x-ms-client-principal-id when authenticated
app.Use(async (context, next) =>
{
// Create a user on current thread from provided header
if (context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID"))
{
// Read headers from Azure
var azureAppServicePrincipalIdHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0];
var azureAppServicePrincipalNameHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0];
// Create claims id
var claims = new Claim[] {
new System.Security.Claims.Claim("http://schemas.microsoft.com/identity/claims/objectidentifier", azureAppServicePrincipalIdHeader),
new System.Security.Claims.Claim("name", azureAppServicePrincipalNameHeader)
};
// Set user in current context as claims principal
var identity = new GenericIdentity(azureAppServicePrincipalIdHeader);
identity.AddClaims(claims);
// Set current thread user to identity
context.User = new GenericPrincipal(identity, null);
};
await next.Invoke();
});
Puedes probar esta biblioteca. Me enfrenté a un problema similar y creé esto para simplificar el uso.
https://github.com/dasiths/NEasyAuthMiddleware
Middleware de Azure App Service Authentication (EasyAuth) para ASP.NET CORE con componentes totalmente personalizables con soporte para depuración local
Hidrata el HttpContext.User registrando un controlador de autenticación personalizado. Para facilitar las cosas cuando se ejecuta localmente, incluso tiene la capacidad de usar un archivo json para cargar reclamos simulados.
Sí, este es un problema de compatibilidad. Desafortunadamente, ASP.NET Core no admite la información de identidad que fluye desde un módulo IIS (como Easy Auth) al código de la aplicación. Esto significa que HttpContext.User y código similar no funcionarán como lo hacen con ASP.NET normal.
La solución por ahora es invocar el punto final /.auth/me de su aplicación web desde el código de su servidor para obtener los reclamos del usuario. Luego, puede almacenar en caché estos datos según corresponda utilizando el valor del encabezado de solicitud x-ms-client-principal-id como clave de caché. La llamada /.auth/me deberá autenticarse correctamente de la misma manera que las llamadas a su aplicación web deben autenticarse (cookie de autenticación o token de encabezado de solicitud).