DIDSearcher.psm1
function Show-Hierarchy { <# .SYNOPSIS Displays an object's values and the 'dot' paths to them .DESCRIPTION A detailed description of the Display-Object function. .PARAMETER TheObject The object that you wish to display .PARAMETER depth the depth of recursion (keep it low!) .PARAMETER Avoid an array of names of objects or arrays you wish to avoid. .PARAMETER Parent For internal use, but you can specify the name of the variable .PARAMETER CurrentDepth For internal use .NOTES https://www.red-gate.com/simple-talk/blogs/display-object-a-powershell-utility-cmdlet/ #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $TheObject, [int]$depth = 5, [Object[]]$Avoid = @('#comment'), [string]$Parent = '$', [int]$CurrentDepth = 0 ) if (($CurrentDepth -ge $Depth) -or ($nulll -eq $TheObject)) { return } #prevent runaway recursion $ObjectTypeName = $TheObject.GetType().Name #find out what type it is if ($ObjectTypeName -in 'HashTable', 'OrderedDictionary') { #If you can, force it to be a PSCustomObject $TheObject = [pscustomObject]$TheObject; $ObjectTypeName = 'PSCustomObject' } #first do objects that cannot be treated as an array. if ($TheObject.Count -le 1 -and $ObjectTypeName -ne 'object[]') { #not something that behaves like an array # figure out where you get the names from if ($ObjectTypeName -in @('PSCustomObject')) { # Name-Value pair properties created by Powershell $MemberType = 'NoteProperty' } else { $MemberType = 'Property' } #now go through the names $TheObject | Get-Member -MemberType $MemberType | Where-Object { $_.Name -notin $Avoid } | ForEach-Object { Try { $child = $TheObject.($_.Name) } Catch { $Child = $null } # avoid crashing on write-only objects $brackets = '' if ($_.Name -like '*.*') { $brackets = "'" } if ($null -eq $child -or #is the current child a value or a null? $child.GetType().BaseType.Name -eq 'ValueType' -or $child.GetType().Name -in @('String', 'String[]')) { [pscustomobject]@{ 'Path' = "$Parent.$brackets$($_.Name)$brackets" 'Value' = $Child } } elseif (($CurrentDepth + 1) -eq $Depth) { [pscustomobject] @{ 'Path' = "$Parent.$brackets$($_.Name)$brackets" 'Value' = $Child } } else { #not a value but an object of some sort Show-Hierarchy -TheObject $child -depth $Depth -Avoid $Avoid ` -Parent "$Parent.$brackets$($_.Name)$brackets" ` -CurrentDepth ($currentDepth + 1) } } } else { #it is an array if ($TheObject.Count -gt 0) { 0..($TheObject.Count - 1) | ForEach-Object { $child = $TheObject[$_]; if (($null -eq $child) -or #is the current child a value or a null? ($child.GetType().BaseType.Name -eq 'ValueType') -or ($child.GetType().Name -in @('String', 'String[]'))) { #if so display it [pscustomobject]@{ 'Path' = "$Parent[$_]" 'Value' = "$($child)" } } elseif (($CurrentDepth + 1) -eq $Depth) { [pscustomobject]@{ 'Path' = "$Parent[$_]" 'Value' = "$($child)" } } else { #not a value but an object of some sort so do a recursive call Show-Hierarchy -TheObject $child -depth $Depth -Avoid $Avoid -parent "$Parent[$_]" ` -CurrentDepth ($currentDepth + 1) } } } else { [pscustomobject]@{ 'Path' = "$Parent" 'Value' = $Null } } } } function Get-DIDJWTDetails { [cmdletbinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [string]$token ) <# .SYNOPSIS Decode a JWT Access Token and convert to a PowerShell Object. JWT Access Token updated to include the JWT Signature (sig), JWT Token Expiry (expiryDateTime) and JWT Token time to expiry (timeToExpiry). .DESCRIPTION Decode a JWT Access Token and convert to a PowerShell Object. JWT Access Token updated to include the JWT Signature (sig), JWT Token Expiry (expiryDateTime) and JWT Token time to expiry (timeToExpiry). .PARAMETER token The JWT Access Token to decode and udpate with expiry time and time to expiry .INPUTS Token from Pipeline .OUTPUTS PowerShell Object .SYNTAX Get-DIDJWTDetails(linked_did) .EXAMPLE PS> Get-DIDJWTDetails('eyJ0eXAiOi........XmN4GnWQAw7OwMA') or PS> 'eyJ0eXAiOi........XmN4GnWQAw7OwMA' | Get-DIDJWTDetails .LINK https://blog.darrenjrobinson.com https://blog.darrenjrobinson.com/jwtdetails-powershell-module-for-decoding-jwt-access-tokens-with-readable-token-expiry-time/ #> if (!$token.Contains(".") -or !$token.StartsWith("eyJ")) { Write-Error "Invalid token" -ErrorAction Stop } # Token foreach ($i in 0..1) { $data = $token.Split('.')[$i].Replace('-', '+').Replace('_', '/') switch ($data.Length % 4) { 0 { break } 2 { $data += '==' } 3 { $data += '=' } } } $decodedToken = [System.Text.Encoding]::UTF8.GetString([convert]::FromBase64String($data)) | ConvertFrom-Json Write-Verbose "JWT Token:" Write-Verbose $decodedToken # Signature foreach ($i in 0..2) { $sig = $token.Split('.')[$i].Replace('-', '+').Replace('_', '/') switch ($sig.Length % 4) { 0 { break } 2 { $sig += '==' } 3 { $sig += '=' } } } Write-Verbose "JWT Signature:" Write-Verbose $sig $decodedToken | Add-Member -Type NoteProperty -Name "sig" -Value $sig # Convert Expiry time to PowerShell DateTime $orig = (Get-Date -Year 1970 -Month 1 -Day 1 -hour 0 -Minute 0 -Second 0 -Millisecond 0) $timeZone = Get-TimeZone $utcTime = $orig.AddSeconds($decodedToken.exp) $offset = $timeZone.GetUtcOffset($(Get-Date)).TotalMinutes #Daylight saving needs to be calculated $localTime = $utcTime.AddMinutes($offset) # Return local time, $decodedToken | Add-Member -Type NoteProperty -Name "expiryDateTime" -Value $localTime # Time to Expiry $timeToExpiry = ($localTime - (get-date)) $decodedToken | Add-Member -Type NoteProperty -Name "timeToExpiry" -Value $timeToExpiry return $decodedToken } function Search-DecentralizedIdentifier { <# .SYNOPSIS Search the ION and Web network for DIDs to discover their keys and endpoints .DESCRIPTION Search the ION and Web network for DIDs to discover their keys and endpoints .PARAMETER ION (optional) Search the ION network .PARAMETER Web (optional - default) Search the Web .EXAMPLE Search-DecentralizedIdentifier -Web -FQDN "https://identity.foundation" Search-DecentralizedIdentifier -Web -FQDN "https://identity.foundation/.well-known/did.json" Search-DecentralizedIdentifier -Web -FQDN "https://identity.foundation" -outputHierarchy Search-DecentralizedIdentifier -ION -identifier 'EiB29JB4R0mbLmJ6_BEYjr8bGZKEPABwFopSNsDJh_Diw' Search-DecentralizedIdentifier -ION -identifier 'EiB29JB4R0mbLmJ6_BEYjr8bGZKEPABwFopSNsDJh_Diw' -outputHierarchy .LINK http://darrenjrobinson.com/ #> [cmdletbinding(DefaultParameterSetName = 'Web')] param( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ParameterSetName = 'ION')] [switch]$ION, [Parameter(Mandatory = $false, ValueFromPipeline = $true, ParameterSetName = 'Web')] [switch]$Web, [Parameter(Mandatory = $true, ParameterSetName = 'ION')] [string]$identifier, [Parameter(Mandatory = $true, ParameterSetName = 'Web')] [System.Uri]$FQDN, [Parameter(ParameterSetName = 'ION')] [Parameter(ParameterSetName = 'Web')] [switch]$outputHierarchy ) try { $result = $null if ($ION) { $result = (Invoke-RestMethod -Uri "https://beta.discover.did.microsoft.com/1.0/identifiers/did:ion:$($identifier)").didDocument } elseif ($Web) { if ($FQDN.Segments.Count -gt 1) { $result = Invoke-RestMethod -Uri $FQDN.AbsoluteUri } else { try { $result = Invoke-RestMethod -Uri "$($FQDN.AbsoluteUri).well-known/did.json" } catch { $result = Invoke-RestMethod -Uri "$($FQDN.AbsoluteUri).well-known/did-configuration.json" } } } else { Write-Output "Specify option -Web (and FQDN) or -ION (and Identifier) to perform DID search." } if ($outputHierarchy) { return $result | Show-Hierarchy } else { return $result } } catch { Write-Error $PSItem.Exception.Message } } # SIG # Begin signature block # MIINSwYJKoZIhvcNAQcCoIINPDCCDTgCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUzrVFVuYyTkRW6s7hHccGNiTF # DuagggqNMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0B # AQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQg # Q29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA # +NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ # 1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0 # sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6s # cKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4Tz # rGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg # 0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIB # ADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUH # AQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYI # KwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFz # c3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0 # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaG # NGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD # QS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYE # FFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en # IZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06 # GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5j # DhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgC # PC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIy # sjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4Gb # T8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHvMIIFVTCC # BD2gAwIBAgIQDOzRdXezgbkTF+1Qo8ZgrzANBgkqhkiG9w0BAQsFADByMQswCQYD # VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln # aWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29k # ZSBTaWduaW5nIENBMB4XDTIwMDYxNDAwMDAwMFoXDTIzMDYxOTEyMDAwMFowgZEx # CzAJBgNVBAYTAkFVMRgwFgYDVQQIEw9OZXcgU291dGggV2FsZXMxFDASBgNVBAcT # C0NoZXJyeWJyb29rMRowGAYDVQQKExFEYXJyZW4gSiBSb2JpbnNvbjEaMBgGA1UE # CxMRRGFycmVuIEogUm9iaW5zb24xGjAYBgNVBAMTEURhcnJlbiBKIFJvYmluc29u # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwj7PLmjkknFA0MIbRPwc # T1JwU/xUZ6UFMy6AUyltGEigMVGxFEXoVybjQXwI9hhpzDh2gdxL3W8V5dTXyzqN # 8LUXa6NODjIzh+egJf/fkXOgzWOPD5fToL7mm4JWofuaAwv2DmI2UtgvQGwRhkUx # Y3hh0+MNDSyz28cqExf8H6mTTcuafgu/Nt4A0ddjr1hYBHU4g51ZJ96YcRsvMZSu # 8qycBUNEp8/EZJxBUmqCp7mKi72jojkhu+6ujOPi2xgG8IWE6GqlmuMVhRSUvF7F # 9PreiwPtGim92RG9Rsn8kg1tkxX/1dUYbjOIgXOmE1FAo/QU6nKVioJMNpNsVEBz # /QIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6XqcQPAYPkt9mV1Dlgw # HQYDVR0OBBYEFOh6QLkkiXXHi1nqeGozeiSEHADoMA4GA1UdDwEB/wQEAwIHgDAT # BgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Axhi9odHRwOi8vY3Js # My5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDA1oDOgMYYvaHR0 # cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwTAYD # VR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cu # ZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUFBwEBBHgwdjAkBggr # BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUFBzAChkJo # dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNzdXJlZElE # Q29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOC # AQEANWoHDjN7Hg9QrOaZx0V8MK4c4nkYBeFDCYAyP/SqwYeAtKPA7F72mvmJV6E3 # YZnilv8b+YvZpFTZrw98GtwCnuQjcIj3OZMfepQuwV1n3S6GO3o30xpKGu6h0d4L # rJkIbmVvi3RZr7U8ruHqnI4TgbYaCWKdwfLb/CUffaUsRX7BOguFRnYShwJmZAzI # mgBx2r2vWcZePlKH/k7kupUAWSY8PF8O+lvdwzVPSVDW+PoTqfI4q9au/0U77UN0 # Fq/ohMyQ/CUX731xeC6Rb5TjlmDhdthFP3Iho1FX0GIu55Py5x84qW+Ou+OytQcA # FZx22DA8dAUbS3P7OIPamcU68TGCAigwggIkAgEBMIGGMHIxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25p # bmcgQ0ECEAzs0XV3s4G5ExftUKPGYK8wCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcC # AQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYB # BAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFP0qX4b8u/At # +3ezHIYCeb3R88ruMA0GCSqGSIb3DQEBAQUABIIBAHh6YInxdf9sr2czr+ZFq4Ro # aLxzzJv1UDGnz2x7/YfJCpydXwzIJWadm+lc8p0Pyy0bKtT3WBm7RnroRsdfuqzE # GTTATubkxURqiGrfJfE4kWwQlw1B+/HYGvhLCnaeWrjRaIIjY6uoo8CJk40uGOyj # TaejdhIANukLE6y5IPkA9ZJx18BAtFGyq50nInmjtHrkgcYRf6DImMSGvyzIWuxE # 392gXTYy8ZOXR69pRkLZj76Vj1kUu6u+LnQBtJyO7ZIbRK67FLY6d5RjmyTvL08k # 4b6pxfsfs7xnyC55GN9IzjxkTcoYLvrg+ca9NV3TKBEriKjYNG93QCcnyZve02U= # SIG # End signature block |