Cómo obtener y decodificar un Access Token de un Service Principal Name (SPN) en Azure con PowerShell

En este artículo, te mostraré cómo obtener un Access Token de un Service Principal Name (SPN) en Azure utilizando PowerShell, y cómo decodificar ese token para ver los claims que contiene. Esta tarea es crucial para desarrolladores y administradores que trabajan con servicios en la nube y necesitan validar la autenticación y los permisos en sus aplicaciones de Azure.

¿Qué es un Access Token?

Un Access Token es un token de seguridad que permite acceder a los recursos protegidos por Azure, como Microsoft Graph o una API personalizada. Este token se emite tras una autenticación correcta y tiene una duración limitada. El token contiene información importante en su estructura como el usuario autenticado, roles, y permisos, los cuales están organizados en forma de claims.

¿Qué son los Claims?

Los claims son declaraciones sobre la identidad del usuario o entidad que realiza la solicitud, como el SPN, y describen aspectos como roles, nombre de usuario, y otros metadatos necesarios para el control de acceso.

Ahora, te guiaré paso a paso por el proceso de obtener el Access Token y decodificarlo para inspeccionar los claims.

Paso 1: Configuración de la aplicación en Azure

El primer paso es asegurarnos de tener configurados los parámetros necesarios para hacer una solicitud de autenticación en Azure. Esto incluye el Client ID, Tenant ID, y Client Secret de tu aplicación registrada en Azure AD, así como el recurso o scope al cual deseas acceder.

En el siguiente script, estos parámetros están definidos:

 

# Configuración de la aplicación
$clientId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
$tenantId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
$resource = "https://graph.microsoft.com"
$scope = "https://graph.microsoft.com/.default"  

clientId: Este es el identificador único de tu aplicación registrada en Azure AD.

tenantId: Identificador del directorio de Azure donde está registrada tu aplicación.

scope: Define el recurso o API a la que estás solicitando acceso. En este caso, usamos Microsoft Graph.

Paso 2: Obtener un Access Token

Para obtener el Access Token, utilizamos el flujo de Client Credentials, que es ideal para aplicaciones confidenciales como las que no interactúan directamente con los usuarios. El script usa MSAL (Microsoft Authentication Library) para realizar esta autenticación.

 

$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
    -ContentType "application/x-www-form-urlencoded" `
    -Body @{
        client_id     = $clientId
        scope         = $scope
        grant_type    = "client_credentials"
        client_secret = "XXXXX~XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX~XXXXXXXXXXXX"  # Para las aplicaciones confidenciales
    }

$accessToken = $tokenResponse.access_token

# Muestra el access token
Write-Host "Access Token:"
Write-Host $accessToken

client_credentials: Este tipo de grant se usa para autenticaciones sin intervención del usuario.

client_secret: Este es el secreto de tu aplicación confidencial, necesario para autenticarte en Azure AD.

Paso 3: Decodificar el Access Token

Los Access Tokens en Azure están en formato JWT (JSON Web Token), que se compone de tres partes: header, payload y signature, separadas por puntos. El payload contiene los claims que queremos inspeccionar.

Para decodificar el token y leer sus claims, usamos una función personalizada:

 

function Decode-JWT {
    param(
        [string]$token
    )
    
    $tokenParts = $token.Split(".")
    if ($tokenParts.Length -ne 3) {
        Write-Host "Token no válido"
        return
    }

    $payload = $tokenParts[1]
    $modPayload = $payload.Replace('_', '/').Replace('-', '+')
    switch ($modPayload.Length % 4) {
        2 { $modPayload += "==" }
        3 { $modPayload += "=" }
    }

    $decodedBytes = [Convert]::FromBase64String($modPayload)
    $jsonPayload = [System.Text.Encoding]::UTF8.GetString($decodedBytes)
    
    # Convertir el JSON a un objeto para fácil lectura
    $claims = $jsonPayload | ConvertFrom-Json
    return $claims
}

$claims = Decode-JWT -token $accessToken
Write-Host "Claims del Access Token:"
$claims

Esta función realiza lo siguiente:

  1. Divide el token en sus tres partes.
  2. Decodifica el payload, que está en formato base64.
  3. Convierte el payload en un objeto JSON que contiene los claims
  4. Devuelve estos claims para poder ser inspeccionados.

Código completo:

# Configuración de la aplicación
$clientId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
$tenantId = XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
$resource = "https://graph.microsoft.com"
$scope = "https://graph.microsoft.com/.default"  # Cambia por el scope adecuado

# Obtener un access token usando MSAL
$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
    -ContentType "application/x-www-form-urlencoded" `
    -Body @{
        client_id     = $clientId
        scope         = $scope
        grant_type    = "client_credentials"
        client_secret = "XXXXX~XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX~XXXXXXXXXXXX"  # Para las aplicaciones confidenciales
    }

$accessToken = $tokenResponse.access_token

# Muestra el access token
Write-Host "Access Token:"
Write-Host $accessToken

# Decodificar el token JWT
function Decode-JWT {
    param(
        [string]$token
    )
    
    $tokenParts = $token.Split(".")
    if ($tokenParts.Length -ne 3) {
        Write-Host "Token no válido"
        return
    }

    # Decodificar el payload del JWT (base64 URL decode)
    $payload = $tokenParts[1]
    $modPayload = $payload.Replace('_', '/').Replace('-', '+')
    switch ($modPayload.Length % 4) {
        2 { $modPayload += "==" }
        3 { $modPayload += "=" }
    }

    $decodedBytes = [Convert]::FromBase64String($modPayload)
    $jsonPayload = [System.Text.Encoding]::UTF8.GetString($decodedBytes)
    
    # Convertir el JSON a un objeto para fácil lectura
    $claims = $jsonPayload | ConvertFrom-Json
    return $claims
}

# Decodifica el token y muestra los claims
$claims = Decode-JWT -token $accessToken
Write-Host "Claims del Access Token:"
$claims

Este sencillo script te permite autenticarte usando un SPN en Azure y obtener un Access Token para luego decodificarlo y ver sus claims. Esto es extremadamente útil cuando trabajas con aplicaciones que requieren autenticación automática y quieres validar los permisos o roles asignados.

:wq!

Deja una respuesta

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