Aws sdk AWS SP-API请求-请求标头中缺少访问令牌

Aws sdk AWS SP-API请求-请求标头中缺少访问令牌,aws-sdk,aws-sdk-ruby,Aws Sdk,Aws Sdk Ruby,我必须按照本指南对AWS API(SP-API)执行签名请求: 我认为这个问题很容易适应AWSAPI的类似要求 下面是使用Faraday的日志请求,我得到了“请求头中缺少访问令牌”作为响应,但它确实存在。我不知道我错过了什么 请求 INFO -- request: GET https://sellingpartnerapi-eu.amazon.com/authorization/v1/authorizationCode?developerId=123456&mwsAuthToken=am

我必须按照本指南对AWS API(SP-API)执行签名请求:

我认为这个问题很容易适应AWSAPI的类似要求

下面是使用Faraday的日志请求,我得到了“请求头中缺少访问令牌”作为响应,但它确实存在。我不知道我错过了什么

请求

INFO -- request: GET https://sellingpartnerapi-eu.amazon.com/authorization/v1/authorizationCode?developerId=123456&mwsAuthToken=amzn.mws.XXXXX&sellingPartnerId=A27E0XXXXX
INFO -- request: host: "sellingpartnerapi-eu.amazon.com"

x-amz-date: "20210504T174042Z"
x-amz-security-token: "IQoJb3JpZ2luX2VjEHoaCWXXXX"
x-amz-content-sha256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4XXXXXXXX"
authorization: "AWS4-HMAC-SHA256 Credential=ASIAXXXXXXXX/20210504/eu-west-1/execute-api/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=0f251c3abca8a73a764671418d64aXXXXXXXXX"
x-amz-access-token: "Atc|MQEBILWaaHz4CKGlzkSiMvrIqXXXXXXX"
user-agent: "App/1.0 (Language=Ruby)"
content-type: "application/json"

INFO -- response: Status 403
INFO -- response: date: "Tue, 04 May 2021 17:40:42 GMT"
content-type: "application/json"
content-length: "187"
connection: "keep-alive"
x-amzn-requestid: "2d51880c-6af3-4d93-9449-18e65b3e89e3"
x-amzn-errortype: "AccessDeniedException"
x-amz-apigw-id: "e0IMMGe-joEFsvA="
请求标头中缺少访问令牌。

首先,我请求一个无授权访问令牌()

然后我签署并构建请求

def get_authorization_code()

        selling_partner_id = 'XXXXXXX'
        region             = 'eu'
        mws_auth_token     = 'amzn.mws.XXXXXX'
        endpoint           = "sellingpartnerapi-eu.amazon.com"

        aws_access_key_id     = ENV['SP_API_KEY']
        aws_secret_access_key = ENV['SP_API_SECRET']
        sts_iam_role_arn      = ENV['SP_IAM_ARN_ROLE']

        # REQUEST STS TOKEN
        aws_region = {
            'na' => 'us-east-1',
            'eu' => 'eu-west-1',
            'fe' => 'us-west-2'
        }[region.to_s] 

        # REQUEST STS TOKEN
        client = Aws::STS::Client.new(
            region: aws_region,
            access_key_id: aws_access_key_id,
            secret_access_key: aws_secret_access_key
        )

        # A “SessionToken” that is the value you must specify for the X-Amz-Security-Token Header
        sts_token       = client.assume_role(role_arn: sts_iam_role_arn, role_session_name: SecureRandom.uuid)

        # URL
        url          = "https://#{endpoint}/authorization/v1/authorizationCode?sellingPartnerId=#{selling_partner_id}&developerId=#{ENV['MWS_EU_DEVELOPER_ID']}&mwsAuthToken=#{mws_auth_token}"
        http_method  = 'GET'
        
        #SIGNED REQUEST
        request_config = {
            service: AWS_SERVICE,
            region: aws_region,
            endpoint: endpoint
        }
        
        # A credential provider is any object that responds to #credentials returning another object that responds to #access_key_id, #secret_access_key, and #session_token
        request_config[:credentials_provider] = sts_token
        
        # SIGNER: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Sigv4/Signer.html
        signer      = Aws::Sigv4::Signer.new(request_config)
        # Sign request: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Sigv4/Signer.html#sign_request-instance_method
        signature   = signer.sign_request(http_method: http_method, url: url)

        # Request Headers
        headers = signature.headers.merge({
            'x-amz-access-token' => request_grantless_access_token['access_token'],
            'user-agent' => "App/1.0 (Language=Ruby)",
            'content-type' => "application/json",
        })

        puts "---- AWS SIGN ----"
        puts "CANONICAL REQUEST: #{signature.canonical_request}"
        puts "HEADERS: #{headers}"
        puts "--------"

        conn = Faraday.new(url: url, headers: headers) do |f|
            f.response :logger # log requests and responses to $stdout
        end

        response = conn.send(http_method.downcase.to_sym) do |req|
            req.body = nil
        end

        return response

def get_authorization_code()

        selling_partner_id = 'XXXXXXX'
        region             = 'eu'
        mws_auth_token     = 'amzn.mws.XXXXXX'
        endpoint           = "sellingpartnerapi-eu.amazon.com"

        aws_access_key_id     = ENV['SP_API_KEY']
        aws_secret_access_key = ENV['SP_API_SECRET']
        sts_iam_role_arn      = ENV['SP_IAM_ARN_ROLE']

        # REQUEST STS TOKEN
        aws_region = {
            'na' => 'us-east-1',
            'eu' => 'eu-west-1',
            'fe' => 'us-west-2'
        }[region.to_s] 

        # REQUEST STS TOKEN
        client = Aws::STS::Client.new(
            region: aws_region,
            access_key_id: aws_access_key_id,
            secret_access_key: aws_secret_access_key
        )

        # A “SessionToken” that is the value you must specify for the X-Amz-Security-Token Header
        sts_token       = client.assume_role(role_arn: sts_iam_role_arn, role_session_name: SecureRandom.uuid)

        # URL
        url          = "https://#{endpoint}/authorization/v1/authorizationCode?sellingPartnerId=#{selling_partner_id}&developerId=#{ENV['MWS_EU_DEVELOPER_ID']}&mwsAuthToken=#{mws_auth_token}"
        http_method  = 'GET'
        
        #SIGNED REQUEST
        request_config = {
            service: AWS_SERVICE,
            region: aws_region,
            endpoint: endpoint
        }
        
        # A credential provider is any object that responds to #credentials returning another object that responds to #access_key_id, #secret_access_key, and #session_token
        request_config[:credentials_provider] = sts_token
        
        # SIGNER: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Sigv4/Signer.html
        signer      = Aws::Sigv4::Signer.new(request_config)
        # Sign request: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Sigv4/Signer.html#sign_request-instance_method
        signature   = signer.sign_request(http_method: http_method, url: url)

        # Request Headers
        headers = signature.headers.merge({
            'x-amz-access-token' => request_grantless_access_token['access_token'],
            'user-agent' => "App/1.0 (Language=Ruby)",
            'content-type' => "application/json",
        })

        puts "---- AWS SIGN ----"
        puts "CANONICAL REQUEST: #{signature.canonical_request}"
        puts "HEADERS: #{headers}"
        puts "--------"

        conn = Faraday.new(url: url, headers: headers) do |f|
            f.response :logger # log requests and responses to $stdout
        end

        response = conn.send(http_method.downcase.to_sym) do |req|
            req.body = nil
        end

        return response