Functions/Test-JwtSignature.ps1

function Test-JwtSignature
{
<#
    .SYNOPSIS
        Validates a JSON Web Token digital signature.
    .DESCRIPTION
        Validates a JSON Web Token digital signature only (no payload) for either RSA or HMAC signed JSON Web Tokens.
    .PARAMETER JsonWebToken
        The JSON Web Token containing the digital signature to be verified.
    .PARAMETER HashAlgorithm
        The RSA hash algorithim for the signature. Acceptable values are SHA256, SHA384, and SHA512. Default value is SHA256.
    .PARAMETER VerificationCertificate
        The certificate that will be used to verify the signature of the JSON Web Token. The private key is NOT needed for signature verification.
    .PARAMETER Key
        This is the secret key used to generate an HMAC signature.
    .PARAMETER JsonWebKey
        The JSON Web Key (X509 certificate public key) to verify the signature of the JSON Web Token per RFC 7517.
    .EXAMPLE
        $jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4QzVkRTlFMDNBNTQ0MDVBQkI2QmEyNDJENjI5MDU0MiIsImlhdCI6MTU5MjU4MTA4OSwiZXhwIjoxNTkyNTgxMzg5LCJzdWIiOiJtZUBjb21wYW55LmNvbSJ9.PkfNMxLIk0qaynr373qxgWR8lTNE5BLApFYhcG3TpK0"
        Test-JwtSignature -JsonWebToken $jwt -HashAlgorithm SHA256 -Key "secret"
 
        Verifies a digital signature for an HAMC signed JSON Web Token against a key with a value of 'secret' (minus the quotes).
    .EXAMPLE
        $cert = Get-Item -Path "Cert:\CurrentUser\My\B31F009EEEEDDFAE34E977626E5A902600CF118C"
        $jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InN4OEFudTd0MzY0MDZYZGlibHFRSmdEUEVZdyIsIng1dCI6InN4OEFudTd0MzY0MDZYZGlibHFRSmdEUEVZdyJ9.eyJzdWIiOiJtZUBjb21wYW55LmNvbSIsImp0aSI6Ijk4NWQyNGNDOTZDMjQxMTA5N0E3NjAzMGY1OTM4RGQzIiwiaWF0IjoxNTkyNTgwOTA1LCJuYmYiOjE1OTI1ODA5MDUsImV4cCI6MTU5MjU4MTIwNX0.whJap3yJIYLIZ4BrK4tVHQVARGstI_omkoo2odOaSpTXZRh104Kyv7J3kiRPaNWKM7t_rpEVylmX-rzY_k_-d7auysVgQL2d-xNa8ZJGmjEemniPy2qRjbpdKDONlija7sbt_7E2n6_0kiwOiu31NemVr1EoWnpGLQeSfgjExuQPHatoKmi5UfijG0P4pWeo3xYyukYE14XOVGYI0ym3yl7gh7YUq9YkKZHvnMulzUoXWImZQ3_0ihC4CwD7QfqKbBuYGCAFtfJ55WHc_iX9EjgVS69aPLIciQmRtvr-xkVG4QApKTLb5NS5dJHKwVxvDojb2OBH5bQM5PMGxpRcIA"
        Test-JwtSignature -JsonWebToken $jwt -HashAlgorithm SHA256 -VerificationCertificate $cert
 
        Verifies a digital signature for an RSA signed JSON Web Token against a certificate with thumbprint B31F009EEEEDDFAE34E977626E5A902600CF118C.
    .EXAMPLE
        $jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjJ5Q3Zabms3azhXNjZ3UjJMWFI5V0Nzd2hBYyIsImtpZCI6IjJ5Q3Zabms3azhXNjZ3UjJMWFI5V0Nzd2hBYyJ9.eyJpYXQiOjE2MTgyNTAzODksIm5iZiI6MTYxODI1MDM4OSwiZXhwIjoxNjE4MjU1MTg5LCJzdWIiOiJ0b255In0.X-RZm-3Hto5U-8Q-Wp1ggqWTFPkO5-Cz9lzoKsH5-1RR9GOrGPuWn-bjIv1YJ46h5Bw-KpiX-dOS47TAq2A0BWdAwczLVA6pzha1WswkT_u3cO1_KSoOjD9qFLjCgk-ns7A48iXpNcOoPBFXgfx8G0rRK68sSnokJ7N2NH-YNUOjg3U7DNJ_-iz8WZ5dNlOvpDsTy0BHMX-lho18sUmakUNpadJr-oD7BXIp--Z57UERBFibppaoxseYRo3VfmhgHibTxP-39mcxU6sH9a99fEEt80hj4w6rZobRxZV-pFPS22B8TBAfVf8L9faMLaXmgV7xtQohqQZgL6oKdJzFPQ"
        $jwk = '
        {
            "kty": "RSA",
            "use": "sig",
            "e": "AQAB",
            "n": "0yvTvlqT5yrk6lDzmK5_i6e-NKW4Bw8J9U62rcWI4IAr-vKaNqitmSwVLr2jJu29xQ__W22iGu584A82AS5N5YrwA6Rek-7WuHinwupFtCN-cCTzJlAcXUxyU7H0LfFxsXS1LUxSl7F_liIKH81QFE5RvI97R9bmbCn_BXpK4pHnTBGJigA8gJQ0U__YFk7AOSFUBeursQfCVPID99FpQ6pyj-h9WgdOneAfWde4SM1Pnovw59T2UT-JO-ObA5WOtvl0xW21djhhBRusVGWJuncNElhhRpUqNSOcsNQVe026zw8dX1wiMs9migQmz_LokH1bHENIuybdK9xBhXRRbw",
            "kid": "2yCvZnk7k8W66wR2LXR9WCswhAc"
        }
        '
        Test-JwtSignature -JsonWebToken $jwt -HashAlgorithm SHA256 -JsonWebKey $jwk
 
        Verifies a JSON Web Token's digital signature against a JSON Web Key.
    .OUTPUTS
        System.Boolean
    .LINK
        https://tools.ietf.org/html/rfc7515
        https://tools.ietf.org/html/rfc7517
        https://tools.ietf.org/html/rfc7519
        New-JwtSignature
        New-JsonWebKeySet
#>


    [CmdletBinding()]
    [OutputType([System.Boolean])]
    Param (
        [Parameter(Mandatory=$true,ValueFromPipeline=$false,Position=0)]
        [ValidateLength(16,8192)][Alias("JWT", "Token")][String]$JsonWebToken,

        [Parameter(Mandatory=$true,Position=1)][ValidateSet("SHA256","SHA384","SHA512")][String]$HashAlgorithm,

        [Parameter(Mandatory=$true,ParameterSetName="RSA",Position=2)][Alias("Certificate", "Cert")]
        [System.Security.Cryptography.X509Certificates.X509Certificate2]$VerificationCertificate,

        [Parameter(Mandatory=$true,ParameterSetName="HMAC",Position=2)][ValidateLength(4,32768)][String]$Key,

        [Parameter(Mandatory=$true,ParameterSetName="JWK",Position=2)][Alias("jwk")][ValidateLength(12, 1073741791)][String]$JsonWebKey
        )

        BEGIN
        {
            $decodeExceptionMessage = "Unable to decode JWT."
            $ArgumentException = New-Object -TypeName ArgumentException -ArgumentList $decodeExceptionMessage
        }
        PROCESS
        {
            [bool]$signatureVerifies = $false

            [bool]$isValidJwt = Test-JwtStructure -JsonWebToken $JsonWebToken -VerifySignaturePresent

            if (-not($isValidJwt))
            {
                Write-Error -Exception $ArgumentException -Category InvalidArgument -ErrorAction Stop
            }

            $jwtHeader = Get-JsonWebTokenHeader -JsonWebToken $JsonWebToken -AsEncodedString
            $jwtPayload = Get-JsonWebTokenPayload -JsonWebToken $JsonWebToken -AsEncodedString
            $jwtSig = Get-JsonWebTokenSignature -JsonWebToken $JsonWebToken -AsEncodedString

            $jwt = "{0}.{1}" -f $jwtHeader, $jwtPayload

            if ($PSCmdlet.ParameterSetName -eq "HMAC")
            {
                [string]$hmacSig = ""
                try
                {
                    $hmacSig = New-JwtSignature -JsonWebToken $jwt -Key $Key -HashAlgorithm $HashAlgorithm -ErrorAction Stop
                }
                catch
                {
                    $signatureExceptionMessage = "Unable to generate signature for given header and payload."
                    $ArgumentException = New-Object -TypeName ArgumentException -ArgumentList $signatureExceptionMessage
                    Write-Error -Exception $ArgumentException -Category InvalidArgument -ErrorAction Stop
                }

                if ($hmacSig -eq $jwtSig)
                {
                    $signatureVerifies = $true
                }
            }
            elseif ($PSCmdlet.ParameterSetName -eq "RSA")
            {
                if ($null -ne $VerificationCertificate.PrivateKey.KeyExchangeAlgorithm)
                {
                    Write-Warning -Message "It is not necessary to perform signature verification with a certificate that has private key!"
                }

                try
                {
                    $signatureVerifies = Test-JwtRsaSignature -JsonWebToken $JsonWebToken -VerificationCertificate $VerificationCertificate -HashAlgorithm $HashAlgorithm -ErrorAction Stop
                }
                catch
                {
                    Write-Error -Exception $_.Exception -ErrorAction Stop
                }
            }
            else # ParameterSetName -eq JWK
            {
                try
                {
                    $signatureVerifies = Test-JwtJwkSignature -JsonWebToken $JsonWebToken -JsonWebKey $JsonWebKey -HashAlgorithm SHA256 -ErrorAction Stop
                }
                catch
                {
                    Write-Error -Exception $_.Exception -ErrorAction Stop
                }

            }

            return $signatureVerifies
        }
}