# Help : Calling an API, having hardtime signing the query

**URL:** <https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931>\
**Category:** PowerShell Help\
**Created:** [April 10, 2024, 2:41pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931 "2024-04-10T14:41:35Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 10, 2024, 2:41pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/1 "2024-04-10T14:41:35Z")

</div>

Hello All,

If anyone can help with this will be awesome.

I have to query an API, but this one has weird signing requirements where the body has to be signed with authorization token which can be made using session ID / access key.

I am able to create the access key and session key, but just cant get the code together for me to be able to sign it.

This i what i came up with but just dosent work.

Any pointers will be very helpful.

# Ignore SSL certificate errors (not recommended for production)

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

# Set the base URL of the web service

$baseUrl = “[https://10.10.10.23:443/api/v1](https://10.10.10.23:443/api/v1)”

# Set the endpoint for the session

$sessionEndpoint = “/sessions”

# Combine base URL with the session endpoint

$sessionUrl = $baseUrl + $sessionEndpoint

# Set your username and password

$username = “ccc”  
$password = “ccc”

# Build the request body

$body = @{  
username = $username  
password = $password  
} | ConvertTo-Json

# Calculate MD5 hash of the request body

$md5 = [System.Security.Cryptography.MD5]::Create()  
$md5Hash = [System.Convert]::ToBase64String($md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($body)))

# Set the Date header to the current date and time in the RFC1123 format

$dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)

# Send the POST request to create a session

$sessionResponse = Invoke-RestMethod -Uri $sessionUrl -Method Post -Body $body -ContentType “application/json;charset=utf-8” -Headers @{  
Date = $dateHeader  
“Content-MD5” = $md5Hash  
}

# Extract the access key and ID from the session response

$accessKey = $sessionResponse.accessKey  
$id = $sessionResponse.id

# Output the access key and ID

Write-Host “Access Key: $accessKey”  
Write-Host “ID: $id”

#Works fine till here

# Set the endpoint for the door

$doorEndpoint = “/doors/SLPORT15”

# Combine base URL with the door endpoint

$doorUrl = $baseUrl + $doorEndpoint

# Set access key and ID obtained from previous response

#$accessKey = “bcdd634f89db4a1e9c9672e2f49bd90c”  
#$id = “bcdd634f89db4a1e9c9672e2f49bd90c” # Assuming the ID and access key are the same based on your example

# Set the Date header to the current date and time in the RFC1123 format

$dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)

# Construct the string to sign

$stringToSign = “GET`n`n`nhost:$baseUrl`ndate:$dateHeader`n/$doorEndpoint”

# Sign the string using the access key

$signature = New-Object System.Security.Cryptography.HMACSHA256  
$signature.Key = [Convert]::FromBase64String($accessKey)  
$signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))  
$signatureBase64 = [Convert]::ToBase64String($signatureBytes)

# Construct the Authorization header

#$authorizationHeader = “AWS $accessKey:$signatureBase64”  
#$authorizationHeader = “AWS $accessKey/$signatureBase64”  
$authorizationHeader = “AWS $accessKey” + “:” + $signatureBase64

# Send the GET request with the Authorization header

$doorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{  
Date = $dateHeader  
Authorization = $authorizationHeader  
}

# Output the response

$doorResponse

I have gone through the documentation but i still cant figure out a way.

7.1.3 Sign a request without a body  
Prerequisites: Use case 7.1.1.  
This use case describes how to sign the following GET request.

GET /api/v1/cards?validTime=20130105T1200&cardHolder=jdoe HTTP/1.1  
Date: Wed, 16 Jan 2013 15:23:02 +0000

The header has no Content-MD5 field and no Content-Type field, so the second and third lines of the string that  
should be signed will be empty. There is also no X-Aah-Date field, so the canonicalized headers part is omitted.  
The parameters validTime and cardHolder are rearranged so they become lexicographically ordered, and the  
resulting string is:

GET\n  
\n  
\n  
Wed, 16 Jan 2013 15:23:02 +0000\n  
/api/v1/cards?cardHolder=jdoe&validTime=20130105T1200

This string, encoded as UTF-8, has a length of 91 characters. It is signed with the session access key AQIDBAUGBwg= (which was received in use case 7.1.1) using HMAC-SHA1.  
The resulting signature in hexadecimal is 341b5e6ed197d4d4dbb2148e67909e2aeedab68e. Encoded as Base 64 it becomes NBtebtGX1NTbshSOZ5CeKu7ato4=. This value is placed together with the session ID to form the header Authorization AWS 342ba291:NBtebtGX1NTbshSOZ5CeKu7ato4=.

There a typescript that one of my mates made but i cant translate it to PS.

---

<div class="post-metadata">

**Author:** ![Austin\_H](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/austin_h/32/4523_2.png) [@Austin\_H](https://forums.powershell.org/u/Austin_H)\
**Post date:** [April 10, 2024, 4:51pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/2 "2024-04-10T16:51:52Z")

</div>

Hi @Vikash_Ghantwal and welcome to forums!

While this is a long post, for visibility please make sure that any code follows coding practices on the forums such that it follows these standards:  
 ![](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/2X/b/bee50c628238f2c076c0504efb6b15f2fb11f002.gif)

I took a look at your code and found some problems that I addressed. I copied your code so reference the code block for line numbers. On line 60 and 69, it can’t interpret what the “:” is being used for so I forced it to use the subexpression `$()` so that it doesn’t evaluate an undeclared variable.

```auto
# Ignore SSL certificate errors (not recommended for production)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

# Set the base URL of the web service
$baseUrl = “https://10.10.10.23:443/api/v1”

# Set the endpoint for the session
$sessionEndpoint = “/sessions”

# Combine base URL with the session endpoint
$sessionUrl = $baseUrl + $sessionEndpoint

# Set your username and password
$username = “ccc”
$password = “ccc”

# Build the request body
$body = @{
  username = $username
  password = $password
} | ConvertTo-Json

# Calculate MD5 hash of the request body
$md5 = [System.Security.Cryptography.MD5]::Create()
$md5Hash = [System.Convert]::ToBase64String($md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($body)))

# Set the Date header to the current date and time in the RFC1123 format
$dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)

# Send the POST request to create a session
$sessionResponse = Invoke-RestMethod -Uri $sessionUrl -Method Post -Body $body -ContentType “application/json;charset=utf-8” -Headers @{
  Date = $dateHeader
  “Content-MD5” = $md5Hash
}

# Extract the access key and ID from the session response
$accessKey = $sessionResponse.accessKey
$id = $sessionResponse.id

# Output the access key and ID
Write-Host “Access Key: $accessKey”
Write-Host “ID: $id”

#Works fine till here

# Set the endpoint for the door
$doorEndpoint = “/doors/SLPORT15”

# Combine base URL with the door endpoint
$doorUrl = $baseUrl + $doorEndpoint

# Set access key and ID obtained from previous response
$accessKey = “bcdd634f89db4a1e9c9672e2f49bd90c”
$id = “bcdd634f89db4a1e9c9672e2f49bd90c” # Assuming the ID and access key are the same based on your example

# Set the Date header to the current date and time in the RFC1123 format
$dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)

# Construct the string to sign
$stringToSign = “GETnnnhost:$($baseUrlndate):$dateHeader`n/$doorEndpoint”

# Sign the string using the access key
$signature = New-Object System.Security.Cryptography.HMACSHA256
$signature.Key = [Convert]::FromBase64String($accessKey)
$signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
$signatureBase64 = [Convert]::ToBase64String($signatureBytes)

# Construct the Authorization header
$authorizationHeader = “AWS $($accessKey):$signatureBase64”
$authorizationHeader = “AWS $accessKey/$signatureBase64”
$authorizationHeader = “AWS $accessKey” + “:” + $signatureBase64

# Send the GET request with the Authorization header
$doorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{
  Date = $dateHeader
  Authorization = $authorizationHeader
}

# Output the response
$doorResponse

```

Is the API documentation publicly available? If so, can you provide that so perhaps we can further assist?

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 11, 2024, 6:09pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/3 "2024-04-11T18:09:19Z")

</div>

Hello @Austin_H,  
Sorry just new to this forum and didnt know the standards.  
Thank you for the demo, ill follow in the future.

You can get a copy from here : [AAH\_Web\_API.pdf - Google Drive](https://drive.google.com/file/d/1YpEyKi-6wmZn0-UgpfoxRFg-p8XW8Nl4/view?usp=drive_link)

Pages 35-41

I also have a typescript if that helps, i very new to this and appreciate all your help.

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 11, 2024, 6:15pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/4 "2024-04-11T18:15:19Z")

</div>

> [@Austin\_H](#):
>
> ```auto
> # Ignore SSL certificate errors (not recommended for production)
> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
> 
> # Set the base URL of the web service
> $baseUrl = “https://10.10.10.23:443/api/v1”
> 
> # Set the endpoint for the session
> $sessionEndpoint = “/sessions”
> 
> # Combine base URL with the session endpoint
> $sessionUrl = $baseUrl + $sessionEndpoint
> 
> # Set your username and password
> $username = “ccc”
> $password = “ccc”
> 
> # Build the request body
> $body = @{
> username = $username
> password = $password
> } | ConvertTo-Json
> 
> # Calculate MD5 hash of the request body
> $md5 = [System.Security.Cryptography.MD5]::Create()
> $md5Hash = [System.Convert]::ToBase64String($md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($body)))
> 
> # Set the Date header to the current date and time in the RFC1123 format
> $dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)
> 
> # Send the POST request to create a session
> $sessionResponse = Invoke-RestMethod -Uri $sessionUrl -Method Post -Body $body -ContentType “application/json;charset=utf-8” -Headers @{
> Date = $dateHeader
> “Content-MD5” = $md5Hash
> }
> 
> # Extract the access key and ID from the session response
> $accessKey = $sessionResponse.accessKey
> $id = $sessionResponse.id
> 
> # Output the access key and ID
> Write-Host “Access Key: $accessKey”
> Write-Host “ID: $id”
> 
> #Works fine till here
> 
> # Set the endpoint for the door
> $doorEndpoint = “/doors/SLPORT15”
> 
> # Combine base URL with the door endpoint
> $doorUrl = $baseUrl + $doorEndpoint
> 
> # Set access key and ID obtained from previous response
> $accessKey = “bcdd634f89db4a1e9c9672e2f49bd90c”
> $id = “bcdd634f89db4a1e9c9672e2f49bd90c” # Assuming the ID and access key are the same based on your example
> 
> # Set the Date header to the current date and time in the RFC1123 format
> $dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)
> 
> # Construct the string to sign
> $stringToSign = “GETnnnhost:$($baseUrlndate):$dateHeader`n/$doorEndpoint”
> 
> # Sign the string using the access key
> $signature = New-Object System.Security.Cryptography.HMACSHA256
> $signature.Key = [Convert]::FromBase64String($accessKey)
> $signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
> $signatureBase64 = [Convert]::ToBase64String($signatureBytes)
> 
> # Construct the Authorization header
> $authorizationHeader = “AWS $($accessKey):$signatureBase64”
> $authorizationHeader = “AWS $accessKey/$signatureBase64”
> $authorizationHeader = “AWS $accessKey” + “:” + $signatureBase64
> 
> # Send the GET request with the Authorization header
> $doorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{
> Date = $dateHeader
> Authorization = $authorizationHeader
> }
> 
> # Output the response
> $doorResponse
> 
> ```

Tried to run the edited code:

Invoke-RestMethod : {  
“status” : 401,  
“code” : 40103,  
“resource” : null,  
“properties” : ,  
“message” : “The supplied session ID does not exist. It may have expired.”,  
“developerMessage” : “The supplied session ID does not exist. It may have expired.”  
}  
At line:29 char:17

- … oorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{
- 

```
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

```

  - CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
  - FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

---

<div class="post-metadata">

**Author:** ![neemobeer](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/neemobeer/32/4087_2.png) [@neemobeer](https://forums.powershell.org/u/neemobeer)\
**Post date:** [April 11, 2024, 7:18pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/5 "2024-04-11T19:18:50Z")

</div>

The error states that you don’t have a valid session id. Are you sure you have to encode that API call?

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 12, 2024, 8:29am UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/6 "2024-04-12T08:29:11Z")

</div>

> [@Austin\_H](#):
>
> ```auto
> # Ignore SSL certificate errors (not recommended for production)
> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
> 
> # Set the base URL of the web service
> $baseUrl = “https://10.10.10.23:443/api/v1”
> 
> # Set the endpoint for the session
> $sessionEndpoint = “/sessions”
> 
> # Combine base URL with the session endpoint
> $sessionUrl = $baseUrl + $sessionEndpoint
> 
> # Set your username and password
> $username = “ccc”
> $password = “ccc”
> 
> # Build the request body
> $body = @{
> username = $username
> password = $password
> } | ConvertTo-Json
> 
> # Calculate MD5 hash of the request body
> $md5 = [System.Security.Cryptography.MD5]::Create()
> $md5Hash = [System.Convert]::ToBase64String($md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($body)))
> 
> # Set the Date header to the current date and time in the RFC1123 format
> $dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)
> 
> # Send the POST request to create a session
> $sessionResponse = Invoke-RestMethod -Uri $sessionUrl -Method Post -Body $body -ContentType “application/json;charset=utf-8” -Headers @{
> Date = $dateHeader
> “Content-MD5” = $md5Hash
> }
> 
> # Extract the access key and ID from the session response
> $accessKey = $sessionResponse.accessKey
> $id = $sessionResponse.id
> 
> # Output the access key and ID
> Write-Host “Access Key: $accessKey”
> Write-Host “ID: $id”
> 
> #Works fine till here
> 
> # Set the endpoint for the door
> $doorEndpoint = “/doors/SLPORT15”
> 
> # Combine base URL with the door endpoint
> $doorUrl = $baseUrl + $doorEndpoint
> 
> # Set access key and ID obtained from previous response
> $accessKey = “bcdd634f89db4a1e9c9672e2f49bd90c”
> $id = “bcdd634f89db4a1e9c9672e2f49bd90c” # Assuming the ID and access key are the same based on your example
> 
> # Set the Date header to the current date and time in the RFC1123 format
> $dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)
> 
> # Construct the string to sign
> $stringToSign = “GETnnnhost:$($baseUrlndate):$dateHeader`n/$doorEndpoint”
> 
> # Sign the string using the access key
> $signature = New-Object System.Security.Cryptography.HMACSHA256
> $signature.Key = [Convert]::FromBase64String($accessKey)
> $signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
> $signatureBase64 = [Convert]::ToBase64String($signatureBytes)
> 
> # Construct the Authorization header
> $authorizationHeader = “AWS $($accessKey):$signatureBase64”
> $authorizationHeader = “AWS $accessKey/$signatureBase64”
> $authorizationHeader = “AWS $accessKey” + “:” + $signatureBase64
> 
> # Send the GET request with the Authorization header
> $doorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{
> Date = $dateHeader
> Authorization = $authorizationHeader
> }
> 
> # Output the response
> $doorResponse
> 
> ```

Hello @neemobeer  
Yeah, the API needs the query o be signed in certain way and im failing at that. @Austin_H cleaned up the code a bit. I am able to make new access and session keys but after that when i need to create an authorization token from those i am not quite sure if that’s correct.

The app has its own API tool which helps in creating the session and authorization header and deals with it in the background, but i wanted to accomplish the same using PS so i can write some functions to manipulate the data.

Below is an example of the exchange when we run the same API call from the APP tools, its called jsoncommander.

```auto
--- Request: ---
POST /api/v1/sessions
Date: Fri, 12 Apr 2024 08:20:24 -0000
Content-Type: application/json;charset=utf-8
Content-MD5: wQsVzvcXwtwzoiZ13iAVWA==

{
    "password": "ccc", 
    "username": "BBB"
}

--- Response: ---
HTTP/1.1 201 Created
content-length: 102
x-oneagent-js-injection: true
set-cookie: dtCookie=v_4_srv_3_sn_31ED9E600C77699539F674B619D9C4EE_perc_100000_ol_0_mul_1_app-3Aea7c4b59f27d43eb_1; Path=/, JSESSIONID=190F3421B033D72F44CE3F85441AC58C; Path=/api/v1; Secure; HttpOnly
server: 
server-timing: dtRpid;desc="1243377219", dtSInfo;desc="0"
x-version: AppWebService 2.35.1.0 / Servlet 1.35.0.1-build0
date: Fri, 12-Apr-24 08:20:25 +0000
content-type: application/json;charset=utf-8

{
    "accessKey": "91cce15eab47484a86ac835b76498c41", 
    "id": "9976b269e1cf49dc9fec90745cda1250"
}

--- Request: ---
GET /api/v1/doors/SLPORT15
Date: Fri, 12 Apr 2024 08:20:25 -0000
Authorization: AWS 9976b269e1cf49dc9fec90745cda1250:A7Km2ObXgjPlmq6YtdMrI2rrsJ8=

--- Response: ---
HTTP/1.1 200 OK
x-oneagent-js-injection: true
transfer-encoding: chunked
set-cookie: dtCookie=v_4_srv_2_sn_3424D3DFD97C9447767390704D3A6E63_perc_100000_ol_0_mul_1_app-3Aea7c4b59f27d43eb_1; Path=/, JSESSIONID=EC42389AC9B137D1E5E0FA2F6F467DA1; Path=/api/v1; Secure; HttpOnly
expires: Thu, 01 Jan 1970 00:00:00 GMT
server: 
server-timing: dtRpid;desc="-556890316", dtSInfo;desc="0"
x-version: AppWebService 2.35.1.0 / Servlet 1.35.0.1-build0
cache-control: private
date: Fri, 12-Apr-24 08:20:25 +0000
content-type: application/json;charset=utf-8

{
    "allowOnOff": false, 
    "autoLock": true, 
    "doorCategory": "common (PMS)", 
    "doorGroup": "Common doors", 
    "doorGroupID": 47, 
    "doorID": 1000007, 
    "doorName": "SLPORT15", 
    "doorType": 0, 
    "escapeReturnMode": 0, 
    "exitButton": 0, 
    "exitButtonOpenTime": 0, 
    "externalRelayMode": false, 
    "id": "SLPORT15", 
    "localName": "SLPORT15", 
    "online": true, 
    "openTime": 4, 
    "roomIntervalStart": 0, 
    "roomIntervalStop": 0, 
    "temporaryAccess": [
        { }

```

Below is the code im trying.

```auto
# Ignore SSL certificate errors (not recommended for production)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

# Set the base URL of the web service
$baseUrl = “https://10.10.10.23:443/api/v1”

# Set the endpoint for the session
$sessionEndpoint = “/sessions”

# Combine base URL with the session endpoint
$sessionUrl = $baseUrl + $sessionEndpoint

# Set your username and password
$username = “ccc”
$password = “ccc”

# Build the request body
$body = @{
  username = $username
  password = $password
} | ConvertTo-Json

# Calculate MD5 hash of the request body
$md5 = [System.Security.Cryptography.MD5]::Create()
$md5Hash = [System.Convert]::ToBase64String($md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($body)))

# Set the Date header to the current date and time in the RFC1123 format
$dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)

# Send the POST request to create a session
$sessionResponse = Invoke-RestMethod -Uri $sessionUrl -Method Post -Body $body -ContentType “application/json;charset=utf-8” -Headers @{
  Date = $dateHeader
  “Content-MD5” = $md5Hash
}

# Extract the access key and ID from the session response
$accessKey = $sessionResponse.accessKey
$id = $sessionResponse.id

# Output the access key and ID
Write-Host “Access Key: $accessKey”
Write-Host “ID: $id”

#Works fine till here ---------------------------------------------------------------------------------------------

# Set the endpoint for the door
$doorEndpoint = “/doors/SLPORT15”

# Combine base URL with the door endpoint
$doorUrl = $baseUrl + $doorEndpoint

# Set access key and ID obtained from previous response
$accessKey = “bcdd634f89db4a1e9c9672e2f49bd90c”
$id = “bcdd634f89db4a1e9c9672e2f49bd90c” # Assuming the ID and access key are the same based on your example

# Set the Date header to the current date and time in the RFC1123 format
$dateHeader = (Get-Date).ToUniversalTime().ToString(“R”)

# Construct the string to sign
$stringToSign = “GETnnnhost:$($baseUrlndate):$dateHeader`n/$doorEndpoint”

# Sign the string using the access key
$signature = New-Object System.Security.Cryptography.HMACSHA256
$signature.Key = [Convert]::FromBase64String($accessKey)
$signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
$signatureBase64 = [Convert]::ToBase64String($signatureBytes)

# Construct the Authorization header
$authorizationHeader = “AWS $($accessKey):$signatureBase64”
$authorizationHeader = “AWS $accessKey/$signatureBase64”
$authorizationHeader = “AWS $accessKey” + “:” + $signatureBase64

# Send the GET request with the Authorization header
$doorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{
  Date = $dateHeader
  Authorization = $authorizationHeader
}

# Output the response
$doorResponse

```

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 19, 2024, 5:14pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/7 "2024-04-19T17:14:20Z")

</div>

Any help will be awesome.

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [April 20, 2024, 7:17am UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/8 "2024-04-20T07:17:47Z")

</div>

Well the first problem you need to solve is you have invalid double quotes. Look at how curly and “fancy” they are. Compare these

```auto
“ccc”

```

to these

```auto
"ccc"

```

This happens due to people copying blog posts/example code that is not formatted as code. Here is your snippet with those fixed. See what happens with this sanitized script

```auto
# Ignore SSL certificate errors (not recommended for production)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

# Set the base URL of the web service
$baseUrl = "https://10.10.10.23:443/api/v1"

# Set the endpoint for the session
$sessionEndpoint = "/sessions"

# Combine base URL with the session endpoint
$sessionUrl = $baseUrl + $sessionEndpoint

# Set your username and password
$username = "ccc"
$password = "ccc"

# Build the request body
$body = @{
  username = $username
  password = $password
} | ConvertTo-Json

# Calculate MD5 hash of the request body
$md5 = [System.Security.Cryptography.MD5]::Create()
$md5Hash = [System.Convert]::ToBase64String($md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($body)))

# Set the Date header to the current date and time in the RFC1123 format
$dateHeader = (Get-Date).ToUniversalTime().ToString("R")

# Send the POST request to create a session
$sessionResponse = Invoke-RestMethod -Uri $sessionUrl -Method Post -Body $body -ContentType "application/json;charset=utf-8" -Headers @{
  Date = $dateHeader
  "Content-MD5" = $md5Hash
}

# Extract the access key and ID from the session response
$accessKey = $sessionResponse.accessKey
$id = $sessionResponse.id

# Output the access key and ID
Write-Host "Access Key: $accessKey"
Write-Host "ID: $id"

#Works fine till here ---------------------------------------------------------------------------------------------

# Set the endpoint for the door
$doorEndpoint = "/doors/SLPORT15"

# Combine base URL with the door endpoint
$doorUrl = $baseUrl + $doorEndpoint

# Set access key and ID obtained from previous response
$accessKey = "bcdd634f89db4a1e9c9672e2f49bd90c"
$id = "bcdd634f89db4a1e9c9672e2f49bd90c" # Assuming the ID and access key are the same based on your example

# Set the Date header to the current date and time in the RFC1123 format
$dateHeader = (Get-Date).ToUniversalTime().ToString("R")

# Construct the string to sign
$stringToSign = "GETnnnhost:$($baseUrlndate):$dateHeader`n/$doorEndpoint"

# Sign the string using the access key
$signature = New-Object System.Security.Cryptography.HMACSHA256
$signature.Key = [Convert]::FromBase64String($accessKey)
$signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
$signatureBase64 = [Convert]::ToBase64String($signatureBytes)

# Construct the Authorization header
$authorizationHeader = "AWS $($accessKey):$signatureBase64"
$authorizationHeader = "AWS $accessKey/$signatureBase64"
$authorizationHeader = "AWS $accessKey" + ":" + $signatureBase64

# Send the GET request with the Authorization header
$doorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{
  Date = $dateHeader
  Authorization = $authorizationHeader
}

# Output the response
$doorResponse

```

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 21, 2024, 10:05am UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/9 "2024-04-21T10:05:15Z")

</div>

> [@krzydoug](#):
>
> ```auto
> # Output the access key and ID
> Write-Host "Access Key: $accessKey"
> Write-Host "ID: $id"
> 
> ```

Hello @krzydoug

Yeah that might be just a copying error but i able able to generate access key and ID using the credentials.

# Output the access key and ID

Write-Host “Access Key: $accessKey”  
Write-Host “ID: $id”

But having issue after that encoding the command.

7.1.3 Sign a request without a body  
Prerequisites: Use case 7.1.1.  
This use case describes how to sign the following GET request.

GET /api/v1/cards?validTime=20130105T1200&cardHolder=jdoe HTTP/1.1  
Date: Wed, 16 Jan 2013 15:23:02 +0000

The header has no Content-MD5 field and no Content-Type field, so the second and third lines of the string that  
should be signed will be empty. There is also no X-Aah-Date field, so the canonicalized headers part is omitted.  
The parameters validTime and cardHolder are rearranged so they become lexicographically ordered, and the  
resulting string is:

GET\n  
\n  
\n  
Wed, 16 Jan 2013 15:23:02 +0000\n  
/api/v1/cards?cardHolder=jdoe&validTime=20130105T1200

This string, encoded as UTF-8, has a length of 91 characters. It is signed with the session access key AQIDBAUGBwg= (which was received in use case 7.1.1) using HMAC-SHA1.  
The resulting signature in hexadecimal is 341b5e6ed197d4d4dbb2148e67909e2aeedab68e. Encoded as Base 64 it becomes NBtebtGX1NTbshSOZ5CeKu7ato4=. This value is placed together with the session ID to form the header Authorization AWS 342ba291:NBtebtGX1NTbshSOZ5CeKu7ato4=.

---

<div class="post-metadata">

**Author:** ![matt-bloomfield](https://avatars.discourse-cdn.com/v4/letter/m/dec6dc/32.png) [@matt-bloomfield](https://forums.powershell.org/u/matt-bloomfield)\
**Post date:** [April 21, 2024, 5:04pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/10 "2024-04-21T17:04:42Z")

</div>

I had a read through the document you provided and I think you’ve got a couple of bits wrong:

```auto
$signature = New-Object System.Security.Cryptography.HMACSHA256

```

Should be:

```auto
$signature = New-Object System.Security.Cryptography.HMACSHA1

```

In the documentation, they’re not converting the key from Base64 and it’s encoded as UTF 8. So this:

```auto
$signature.Key = [Convert]::FromBase64String($accessKey)

```

Should be:

```auto
$signature.Key = [Text.Encoding]::UTF8.GetBytes($accessKey)

```

If you change those lines, you can get the same signed values as given in the example.

```auto
$stringToSign = @"
GET

Wed, 16 Jan 2013 15:23:02 +0000
/api/v1/cards?cardHolder=jdoe&validTime=20130105T1200
"@

$accessKey = 'AQIDBAUGBwg='

$signature = New-Object System.Security.Cryptography.HMACSHA1
$signature.Key = [Text.Encoding]::UTF8.GetBytes($accessKey)
$signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
$signatureBase64 = [Convert]::ToBase64String($signatureBytes)

Write-Output "HEX: $(($signatureBytes | ForEach-Object {$_.ToString('X2') }) -join '')"
Write-Output "Base64: $signatureBase64"

```

Output:

```auto
HEX: 341B5E6ED197D4D4DBB2148E67909E2AEEDAB68E
Base64: NBtebtGX1NTbshSOZ5CeKu7ato4=

```

If testing the above as a script, you’ll need to make sure that you save it in Unix LF rather than Windows CRLF format otherwise you won’t get the expect hash values.

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 22, 2024, 11:32am UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/11 "2024-04-22T11:32:13Z")

</div>

> [@matt-bloomfield](#):
>
> ```auto
> $signature = New-Object System.Security.Cryptography.HMACSHA1
> $signature.Key = [Text.Encoding]::UTF8.GetBytes($accessKey)
> $signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
> $signatureBase64 = [Convert]::ToBase64String($signatureBytes)
> 
> ```

Hello @matt-bloomfield,

Thank you for the pointers. I am just trying it on a windows machine via PS ISE.

There is a proprietary app used for these curls which take care of the session ID and encoding process by itself. I have the output from the app, but ive never been able to accomplish to get it going from PS.

```auto
--- Request: ---
POST /api/v1/sessions
Date: Mon, 22 Apr 2024 09:41:27 -0000
Content-Type: application/json;charset=utf-8
Content-MD5: wQsVzvcXwtwzoiZ13iAVWA==

{
    "password": "ABC", 
    "username": "ABC"
}

--- Response: ---
HTTP/1.1 201 Created
content-length: 102
x-oneagent-js-injection: true
set-cookie: dtCookie=v_4_srv_2_sn_BCB2DF878103ED812F2269A9C8E8DA7F_perc_100000_ol_0_mul_1_app-3Aea7c4b59f27d43eb_1; Path=/, JSESSIONID=6EC83D365BCD50CBBB4BFD87A601EBF6; Path=/api/v1; Secure; HttpOnly
server: 
server-timing: dtRpid;desc="-542391961", dtSInfo;desc="0"
x-version: AppWebService 2.35.1.0 / Servlet 1.35.0.1-build0
date: Mon, 22-Apr-24 09:41:28 +0000
content-type: application/json;charset=utf-8

{
    "accessKey": "98e7aaa338a14b6e8c72a70094766d54", 
    "id": "2ce1c53953d4416f884b854deb2239ce"
}

--- Request: ---
GET /api/v1/doors/SLPORT15
Date: Mon, 22 Apr 2024 09:41:29 -0000
Authorization: AWS 2ce1c53953d4416f884b854deb2239ce:6fXdL/55HJMULziVqgLFm2G4xLo=

```

If i point these to the variables in the script, $accessKey and $id

```auto
 {
    "accessKey": "98e7aaa338a14b6e8c72a70094766d54", 
    "id": "2ce1c53953d4416f884b854deb2239ce"
}

```

I cant seem to get the authorization token right if i try from the Script

From proprietary app

```auto
Authorization: AWS 2ce1c53953d4416f884b854deb2239ce:6fXdL/55HJMULziVqgLFm2G4xLo=

```

From PS Script

```auto
# Sign the string using the access key
$signature = New-Object System.Security.Cryptography.HMACSHA1
$signature.Key = [Text.Encoding]::UTF8.GetBytes($accessKey)
$signatureBytes = $signature.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
$signatureBase64 = [Convert]::ToBase64String($signatureBytes)

PS C:\Temp> $authorizationHeader = "AWS $id" + ":" + $signatureBase64

PS C:\Temp> $authorizationHeader
AWS 2ce1c53953d4416f884b854deb2239ce:wHOY34qOsC0Y1T5Gh+wS4CXjwIc=

```

Im a bit new to calling API’s via PS and really appreciate your time.

---

<div class="post-metadata">

**Author:** ![grey0ut](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/grey0ut/32/5310_2.png) [@grey0ut](https://forums.powershell.org/u/grey0ut)\
**Post date:** [April 22, 2024, 3:08pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/12 "2024-04-22T15:08:20Z")

</div>

Coming in late here, but I’m able to get the same token as the proprietary app by following the method @matt-bloomfield shared.  
From your recent example @Vikash_Ghantwal I used this as the string to sign:

```auto
$Stringtosign = @"
GET

Mon, 22 Apr 2024 09:41:29 -0000
/api/v1/doors/SLPORT15
"@

```

That’s the HTTP Verb, a blank line for the content-MD5header, a blank line for the content-type header. Then the date the request was sent and the resource that was requested.  
Then I stored the access key in a string variable called $AccessKey and ran this:

```auto
$signature = new-object System.Security.Cryptography.HMACSHA1
$signature.key = [text.encoding]::utf8.GetBytes($accesskey)
$signaturebytes = $signature.computehash([text.encoding]::utf8.getbytes($stringtosign))
$signaturebase64 = [convert]::ToBase64String($signaturebytes)

```

And the resulting value of the $signaturebase64 ended up being:  
`6fXdL/55HJMULziVqgLFm2G4xLo=`

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 22, 2024, 9:21pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/13 "2024-04-22T21:21:04Z")

</div>

> [@Vikash\_Ghantwal](#):
>
> `Mon, 22-Apr-24 09:41:28 +0000`

Hello @grey0ut,

Thank you for pointing out, my $Stringtosign was wrong , the $dateHeader ended with GMT instead of +0000.

I have fixed that and now able to see the same results 🙂 ive never come so close even after 2 months of trying.

Now, how do i send the encoded string ?  
I was using the below, but i get an error. Am i using to many headers ?

```auto
# Send the GET request with the Authorization header
$doorResponse = Invoke-RestMethod -Uri $doorUrl -Method Get -Headers @{
    Date = $dateHeader
    Authorization = $authorizationHeader
}

```

Also to create the $doorUrl i use the below. Is it correct or do i need to only send $baseurl

```auto
# Set the base URL of the web service
$baseUrl = "https://10.125.192.113:443"

# Set the endpoint for the door
$doorEndpoint = "/api/v1/doors/SLPORT15"

# Combine base URL with the door endpoint
$doorUrl = $baseUrl + $doorEndpoint

```

So close here 🙂

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 23, 2024, 12:34pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/14 "2024-04-23T12:34:33Z")

</div>

@matt-bloomfield@grey0ut  
I thank you all for your input, ive finally managed to get it working. Thank you for your time guys 🙂  
Cheers,  
Vikash

---

<div class="post-metadata">

**Author:** ![Vikash\_Ghantwal](https://avatars.discourse-cdn.com/v4/letter/v/f07891/32.png) [@Vikash\_Ghantwal](https://forums.powershell.org/u/Vikash_Ghantwal)\
**Post date:** [April 23, 2024, 12:35pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/15 "2024-04-23T12:35:43Z")

</div>

Sorry as a new user i can only tag 2 people at a time.  
@Austin_H @neemobeer  
I thank you all for your input, ive finally managed to get it working. Thank you for your time guys 🙂  
Cheers,  
Vikash

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [May 23, 2024, 12:36pm UTC](https://forums.powershell.org/t/help-calling-an-api-having-hardtime-signing-the-query/23931/16 "2024-05-23T12:36:32Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
