koalazak / dorita980

Unofficial iRobot Roomba and Braava (i7/i7+, 980, 960, 900, e5, 690, 675, m6, etc) node.js library (SDK) to control your robot
MIT License
931 stars 147 forks source link

Getting "The request signature we calculated does not match the signature you provided" error while accessing Roomba API #179

Closed rahmanonik18 closed 7 months ago

rahmanonik18 commented 11 months ago

I'm trying to access a Roomba API using the AWS authentication method in Python, and I keep getting the following error message:

{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method."
}

Here's the general structure of the request I'm sending:

GET [Endpoint]
Headers:
- x-amz-content-sha256
- Authorization (including Credential, SignedHeaders, Signature)
- Content-type
- X-Amz-Date
- Accept
- Host
- x-amz-security-token
- User-Agent
- Connection
- Accept-Encoding

I have also created a separate authentication module (awsauthentication.py). Here's a snippet from that:

import requests, datetime, hashlib, hmac

#Authentiction : aws4-hmac-sha256

class AwsRequest:
    def __init__(self, region, access_key, secret_key, session_token, service):
        self.region = region
        self.access_key = access_key
        self.secret_key = secret_key
        self.session_token = session_token
        self.service = service

    #Return signature using HMAC-SHA256 from key + msg
    def sign(self, key, msg):
        return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

    #Generate AWS4-HMAC-SHA256 signing key from key,date stamp, region, and service name
    def generate_signature_key(self, key, dateStamp, regionName, serviceName):
        key_date = self.sign(('AWS4' + key).encode('utf-8'), dateStamp)
        key_region = self.sign(key_date, regionName)
        key_service = self.sign(key_region, serviceName)
        key_sign = self.sign(key_service, 'aws4_request')
        return key_sign

    def get(self, host, uri, query=""):

        method = "GET"
        timenow = datetime.datetime.utcnow() #Current UTC timenow
        amzdate = timenow.strftime('%Y%m%dT%H%M%SZ') #Datetime headers
        datestamp = timenow.strftime('%Y%m%d') # Datetime credential scope

        canonical_uri = uri 
        canonical_querystring = query
        canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n' + 'x-amz-security-token:' + self.session_token + '\n'

        signed_headers = 'host;x-amz-date;x-amz-security-token'
        payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
        canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash

        algorithm = 'AWS4-HMAC-SHA256'
        credential_scope = datestamp + '/' + self.region + '/' + self.service + '/' + 'aws4_request'
        string_to_sign = algorithm + '\n' +  amzdate + '\n' +  credential_scope + '\n' +  hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()

        signing_key = self.generate_signature_key(self.secret_key, datestamp, self.region, self.service)
        signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()

        authorization_header = algorithm + ' ' + 'Credential=' + self.access_key + '/' + credential_scope + ', ' +  'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
        headers = {'x-amz-security-token': self.session_token, 'x-amz-date':amzdate, 'Authorization':authorization_header}

        req = "https://%s%s" % (host, uri)
        if query != "":
            req += "?%s" % query
        return requests.get(req, headers=headers)

I have verified that the keys, tokens, and other sensitive information are correct, but I am still unable to access the API.

Questions:

Is there anything I'm missing in the header or request format? How can I correctly calculate the request signature to match what the server expects?

I have attached the image for the api i want to get response. What mistake I am making in creating signature? Screenshot 2023-08-07 235134

koalazak commented 7 months ago

you should check aws documentation, sorry.