Saltar al contenido

¿Cómo validar el token de seguridad de Azure AD?

Te doy la bienvenida a proyecto on line, en este sitio vas a hallar la respuesta de lo que buscas.

Solución:

Hay dos pasos para verificar el token. Primero, verifique la firma del token para asegurarse de que Azure Active Directory emitió el token. En segundo lugar, verifique las afirmaciones en el token según la lógica empresarial.

Por ejemplo, necesitamos verificar el iss y aud reclamar si estaba desarrollando una aplicación de inquilino único. Y también necesita verificar el nbf para asegurarse de que el token no esté vencido. Más reclamos que puede consultar aquí.

A continuación, la descripción es de aquí sobre los detalles de la verificación de firmas. (Nota: El ejemplo siguiente usa el punto de conexión de Azure AD v2. Debe usar el punto de conexión que corresponda al punto de conexión que usa la aplicación cliente).

El token de acceso de Azure AD es un JSON Web Token (JWT) que está firmado por Security Token Service en privado key.

El JWT incluye 3 partes: encabezado, datos y firma. Técnicamente, podemos utilizar el público key para validar el token de acceso.

Primer paso: recuperar y almacenar en caché los tokens de canto (público key)

Punto final: https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

Entonces podemos usar el JwtSecurityTokenHandler para verificar el token usando el código de muestra a continuación:

 public JwtSecurityToken Validate(string token)
 
     string stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";

     ConfigurationManager configManager = new ConfigurationManager(stsDiscoveryEndpoint);

     OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;

     TokenValidationParameters validationParameters = new TokenValidationParameters
     
         ValidateAudience = false,
         ValidateIssuer = false,
         IssuerSigningTokens = config.SigningTokens,
         ValidateLifetime = false
     ;

     JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();

     SecurityToken jwt;

     var result = tokendHandler.ValidateToken(token, validationParameters, out jwt);

     return jwt as JwtSecurityToken;
 

Y si estaba utilizando los componentes OWIN en su proyecto, es más fácil verificar el token. Podemos usar el siguiente código para verificar el token:

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
            new WindowsAzureActiveDirectoryBearerAuthenticationOptions
            
                Audience = ConfigurationManager.AppSettings["ida:Audience"],
                Tenant = ConfigurationManager.AppSettings["ida:Tenant"]
            );

Luego, podemos usar el código a continuación para verificar el ‘alcance’ en el token:

public IEnumerable Get()

    // user_impersonation is the default permission exposed by applications in AAD
    if (ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/scope").Value != "user_impersonation")
    
        throw new HttpResponseException(new HttpResponseMessage 
          StatusCode = HttpStatusCode.Unauthorized,
          ReasonPhrase = "The Scope claim does not contain 'user_impersonation' or scope claim not found"
        );
    
    ...

Y aquí hay una muestra de código que protegió la API web con Azure AD:

Proteger un API web usando tokens de portador de Azure AD

Solo quería agregar algo a la respuesta de Fei para las personas que usan .net Core 2.0

Tendrás que modificar 2 líneas del Validate(string token) método.

 var configManager = new ConfigurationManager(
        stsDiscoveryEndpoint,
        new OpenIdConnectConfigurationRetriever()); //1. need the 'new OpenIdConnect...'

 OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;
 TokenValidationParameters validationParameters = new TokenValidationParameters
 
     //decode the JWT to see what these values should be
     ValidAudience = "some audience",
     ValidIssuer = "some issuer",

     ValidateAudience = true,
     ValidateIssuer = true,
     IssuerSigningKeys = config.SigningKeys, //2. .NET Core equivalent is "IssuerSigningKeys" and "SigningKeys"
     ValidateLifetime = true
 ;

Pero si no está utilizando OWIN en sus proyectos, será un poco difícil o al menos llevará mucho tiempo. Este artículo es un gran recurso.

Y porque no tengo mucho que agregar a lo anterior, excepto el código detallado .. Aquí hay algo que puede serle útil:

 public async Task CreatePrincipleAsync()
    
        AzureActiveDirectoryToken azureToken = Token.FromJsonString();
        var allParts = azureToken.IdToken.Split(".");
        var header = allParts[0];
        var payload = allParts[1];
        var idToken = payload.ToBytesFromBase64URLString().ToAscii().FromJsonString();

        allParts = azureToken.AccessToken.Split(".");
        header = allParts[0];
        payload = allParts[1];
        var signature = allParts[2];
        var accessToken = payload.ToBytesFromBase64URLString().ToAscii().FromJsonString();

        var accessTokenHeader = header.ToBytesFromBase64URLString().ToAscii().FromJsonString();
        var isValid = await ValidateToken(accessTokenHeader.kid, header, payload, signature);
        if (!isValid)
        
            throw new SecurityException("Token can not be validated");
        
        var principal = await CreatePrincipalAsync(accessToken, idToken);
        return principal;
    



    private async Task ValidateToken(string kid, string header, string payload, string signature)
    
        string keysAsString = null;
        const string microsoftKeysUrl = "https://login.microsoftonline.com/common/discovery/keys";

        using (var client = new HttpClient())
        
            keysAsString = await client.GetStringAsync(microsoftKeysUrl);
        
        var azureKeys = keysAsString.FromJsonString();
        var signatureKeyIdentifier = azureKeys.Keys.FirstOrDefault(key => key.kid.Equals(kid));
        if (signatureKeyIdentifier.IsNotNull())
        
            var signatureKey = signatureKeyIdentifier.x5c.First();
            var certificate = new X509Certificate2(signatureKey.ToBytesFromBase64URLString());
            var rsa = certificate.GetRSAPublicKey();
            var data = string.Format("0.1", header, payload).ToBytes();

            var isValidSignature = rsa.VerifyData(data, signature.ToBytesFromBase64URLString(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
            return isValidSignature;
        

        return false;
    

Hay algunas funciones que utilizo aquí que no están disponibles para usted, son autodescriptivas.

valoraciones y comentarios

Si haces scroll puedes encontrar las notas de otros administradores, tú además tienes la libertad de dejar el tuyo si dominas el tema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *