Public/ConvertFrom-JwtToken.ps1

function ConvertFrom-JwtToken
{
    <#
        .SYNOPSIS
            Converts a JWT token string.
        .DESCRIPTION
            Converts a JWT token string to an object containing members representing the header, payload and signature of the raw token.
        .PARAMETER Token
            A string containing the raw JWT token.
        .PARAMETER AsJson
            A switch specifying whether or not to return the parts as JSON (except the signature).
        .PARAMETER ConvertDate
            A switch specifying whether or not to convert the date from seconds since Unix epoch to DateTime (affected fields are 'nbf', 'exp' and 'auth_time' in the payload).
            This parameter has no effect if AsJson is specified.
        .INPUTS
            System.String
            You can pipe a value for the raw token to this cmdlet.
        .OUTPUTS
            System.Management.Automation.PSCustomObject
            Returns a PSCustomObject containing a description of the token.
        .EXAMPLE
            ConvertFrom-JwtToken -Token $MyRawToken
 
            Description
            -----------
            This example will return an object representing the token.
        .EXAMPLE
            ConvertFrom-JwtToken -Token $MyRawToken -AsJson
 
            Description
            -----------
            This example will return an object representing the token with header and payload as JSON.
        .EXAMPLE
            $MyRawToken | ConvertFrom-JwtToken -ConvertDate
 
            Description
            -----------
            This example will return an object representing the token dates converted from seconds since Unix epoch to DateTime.
        .NOTES
            Signature is kept raw but padded, so it can be offuscated if needed.
        .LINK
            ConvertTo-JwtToken
        .LINK
            https://tools.ietf.org/html/rfc7519
        .LINK
            https://jwt.io/
    #>

    [CmdLetBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript( { if (!(Test-JwtToken -Token $_)) { throw ($script:LocalizedData.ConvertFromJwtToken.Error.InvalidToken -f $_) } else { $true } })]
        [string] $Token,
        [Parameter(Mandatory = $false)]
        [switch] $AsJson,
        [Parameter(Mandatory = $false)]
        [switch] $ConvertDate
    )
 
    begin
    {
        Write-Debug ($script:LocalizedData.Global.Debug.Entering -f $PSCmdlet.MyInvocation.MyCommand)
        $PartNames = Get-JwtTokenPart
    }
    process
    {
        try
        {
            if ($Token)
            {
                Write-Debug ($script:LocalizedData.ConvertFromJwtToken.Debug.TokenBefore -f $Token)
                $Token = $Token.Replace('-', '+').Replace('_', '/')
                Write-Debug ($script:LocalizedData.ConvertFromJwtToken.Debug.TokenAfter -f $Token)
                $TokenObject = New-Object -TypeName psobject
                
                $i = 0
                $Token.Split(".") | ForEach-Object {
                    $Part = $_
                    Write-Debug ($script:LocalizedData.ConvertFromJwtToken.Debug.PartBeforePadding -f $PartNames[$i], $Part)
                    while ($Part.Length % 4) { $Part += "=" }
                    Write-Debug ($script:LocalizedData.ConvertFromJwtToken.Debug.PartAfterPadding -f $PartNames[$i], $Part)
                    if ($PartNames[$i] -ne "Signature")
                    {
                        Write-Verbose ($script:LocalizedData.ConvertFromJwtToken.Verbose.ConvertToBase64 -f $PartNames[$i].ToLower())
                        $Part = [System.Text.Encoding]::ASCII.GetString([system.convert]::FromBase64String($Part))
                        Write-Debug ($script:LocalizedData.ConvertFromJwtToken.Debug.PartAsJson -f $PartNames[$i], $Part)
                        if (!$AsJson) { $Part = $Part | ConvertFrom-Json }
                        if (($PartNames[$i] -eq "Payload") -and $ConvertDate -and !$AsJson)
                        {
                            Get-JwtTokenPayloadDateField | Where-Object { $Part.$_ } | ForEach-Object { 
                                Write-Verbose ($script:LocalizedData.ConvertFromJwtToken.Verbose.ConvertFromUnixEpoch -f $_)
                                Write-Debug ($script:LocalizedData.ConvertFromJwtToken.Debug.DateBefore -f $_, $Part.$_)
                                $Part.$_ = (Get-Date "1970-01-01").AddSeconds($Part.$_)
                                Write-Debug ($script:LocalizedData.ConvertFromJwtToken.Debug.DateAfter -f $_, $Part.$_)
                            }
                        }
                    }
                    $TokenObject | Add-Member -MemberType NoteProperty -Name $PartNames[$i] -Value $Part | Out-Null
                    $i++
                }
                
                $TokenObject
            }
        }
        catch
        {
            Write-Error $_
        }
    }
    end
    {
        Write-Debug ($script:LocalizedData.Global.Debug.Leaving -f $PSCmdlet.MyInvocation.MyCommand)
    }
}