Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doing a resolveCustomer() call using temporary credentials. #10

Open
slimandslam opened this issue Apr 14, 2021 · 14 comments
Open

Doing a resolveCustomer() call using temporary credentials. #10

slimandslam opened this issue Apr 14, 2021 · 14 comments

Comments

@slimandslam
Copy link

This might be useful for sites that want to have unauthenticated users doing the resolveCustomer() call.

I am successfully generating an AccessKey, SecretKey, and SessionToken associated with a Role that permits the temporary user to make resolveCustomer() calls.

I can prove that these credentials can successfully do a resolveCustomer() call by setting env vars:
(without setting these, it can't find credentials).

export AWS_ACCESS_KEY_ID=xxxxx
export AWS_SECRET_ACCESS_KEY=yyyyy
export AWS_SESSION_TOKEN=zzzz

And then doing the relevant CLI call:

aws meteringmarketplace resolve-customer --registration-token asdfa --region us-west-2

This should return an "InvalidToken" error.

Works great. However, I want to do this using the JavaScript SDK v3.

My attempt looks like this:

const tempCredentials =  {
  accessKeyId: AccessKeyId,
  secretAccessKey: SecretAccessKey,
  sessionToken: SessionToken
};

 const marketplacemetering = new MarketplaceMeteringClient({
   region: 'us-west-2',
   credentials: tempCredentials
 });

 const resolveCustomerParams = {
     RegistrationToken: 'asdfa',
 };

 const resolve = new ResolveCustomerCommand(resolveCustomerParams);

 try {

    const data = await marketplacemetering.send(resolve);
    return data;

 } catch (error)  {

   return error;

 }

The call returns "TypeError: Failed to fetch" which usually means that the Api call is just not setup properly.
What I'm expecting is a 400 error of type InvalidToken.
Any thoughts?

@dblock
Copy link

dblock commented Apr 14, 2021

I am going to speculate that `credentials` needs to be a credentials object like [here](https://github.com/aws-samples/aws-dataexchange-api-samples/blob/master/subscribers/javascript/all-entitled-datasets/index.ts#L3). Does that change anything?
const marketplacemetering = new MarketplaceMeteringClient({
   region: 'us-west-2',
   credentials: new Credentials(tempCredentials)
 });

Also double-check that tempCredentials has values.

@slimandslam
Copy link
Author

slimandslam commented Apr 14, 2021

Where do I get the Credentials object in JavaScript SDK Version 3?
In SDK v3, the modules are imported piecemeal, e.g.

import { STSClient, AssumeRoleWithWebIdentityCommand } from "@aws-sdk/client-sts";

Your linked example would require (I think) npm install aws-sdk. which would install all of JavaScript SDK v2.
Reference: https://www.npmjs.com/package/aws-sdk

@dblock
Copy link

dblock commented Apr 14, 2021

Ok, I am wrong.

First, credentials now are brought in via providers that implement a basic Credentials interface, so you can just use a plain object/hash as you did, or a specific provider, such as fromEnv.

import { fromEnv } from '@aws-sdk/credential-provider-env'

const dataexchange = new DataExchange({
  region: process.env.AWS_REGION || 'us-east-1',
  credentials: fromEnv()
});

So that's not the problem here.

I upgraded a sample in aws-samples/aws-dataexchange-api-samples#45 to AWS SDK v3 and I didn't need to do that anymore.

I'll gladly take a look at your code if you can put it up on GitHub, and tell me how to reproduce the issue?

@slimandslam
Copy link
Author

This code fragment should be all that you need. Just start with a sessiontoken, Accesskey, and secretkey that have the ability to make the resolveCustomer() call. If this works properly, you should get a 400 response code and an "InvalidToken" error.

import { MarketplaceMeteringClient, ResolveCustomerCommand } from "@aws-sdk/client-marketplace-metering";

const tempCredentials =  {
  accessKeyId: AccessKeyId,
  secretAccessKey: SecretAccessKey,
  sessionToken: SessionToken
};

 const marketplacemetering = new MarketplaceMeteringClient({
   region: 'us-west-2',
   credentials: tempCredentials
 });

 const resolveCustomerParams = {
     RegistrationToken: 'asdfa',
 };

 const resolve = new ResolveCustomerCommand(resolveCustomerParams);

 try {

    const data = await marketplacemetering.send(resolve);
    console.log(data);

 } catch (error)  {

   console.log(error)

 }

@dblock
Copy link

dblock commented Apr 14, 2021

I put this code up in aws-samples/aws-marketplace-api-samples#4 and I get the expected error.

$ node -v
v12.9.0
$ npm -v
6.10.2
$ npm run build
{ InvalidTokenException: Registration token is invalid
    at deserializeAws_json1_1ResolveCustomerCommandError (/Users/dblock/source/aws-mp/aws-marketplace-api-samples/dblock/marketplace-metering-api/node_modules/@aws-sdk/client-marketplace-metering/protocols/Aws_json1_1.ts:535:39)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  name: 'InvalidTokenException',
  '$fault': 'client',
  '$metadata':
   { httpStatusCode: 400,
     requestId: 'efaed4ea-7a2f-421c-b43b-2aedb486244b',
     extendedRequestId: undefined,
     cfId: undefined,
     attempts: 1,
     totalRetryDelay: 0 } }

@slimandslam
Copy link
Author

slimandslam commented Apr 14, 2021

Yup. Works for me too. But when I use the exact same code in a React component, I get the dreaded

TypeError: Failed To Fetch

It claims to be a CORS error (I'm running from Localhost in a web browser):

:3000/signup?x-amzn-marketplace-token=23423dd:1 Access to fetch at 'https://metering.marketplace.us-west-2.amazonaws.com/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

But if it is a CORS error, why can I successfully make STSClient and CognitoIdentityClient API calls in the web browser just before that without any CORS errors?

@dblock
Copy link

dblock commented Apr 14, 2021

Aha, so this is the actual problem. This is because metering does not support/allow CORS, see https://github.com/aws/aws-sdk-js/blob/master/SERVICES.md that says which ones do and which ones don't.

I am not sure what the rationale is for allowing/disallowing CORS. What are you trying to build?

@slimandslam
Copy link
Author

My SaaS needs to make a resolveCustomer() call to determine if the incoming x-amzn-marketplace-token token is valid. Since this is a serverless SaaS (eventually, JS running from an S3 bucket), the call is from JS.

@dblock
Copy link

dblock commented Apr 14, 2021

I have flagged this to someone in AWS who's close to this service, but I think it's a feature request at this point, so you should probably open a ticket with support, and ask for it, pointing this conversation.

@slimandslam
Copy link
Author

I see that the resolveCuatomer() call is in a Lambda function in this project. Do the AWS access credentials have to be tied to a specific account in order to get the right results for resolvecustomer() or can anyone with permission to make the call do it?

https://github.com/aws-samples/aws-marketplace-serverless-saas-integration/blob/master/src/register-new-subscriber.js

@dblock
Copy link

dblock commented Apr 15, 2021

@gjoshevski care to comment on ^?

@malfree
Copy link

malfree commented Apr 15, 2021

I see that the resolveCuatomer() call is in a Lambda function in this project. Do the AWS access credentials have to be tied to a specific account in order to get the right results for resolvecustomer() or can anyone with permission to make the call do it?

From https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_ResolveCustomer.html

Note
The API needs to called from the seller account id used to publish the SaaS application to successfully resolve the token.

@slimandslam
Copy link
Author

The next (obvious?) question is: It's very common to have development and production in separate AWS accounts. What's the best practice for testing Marketplace integration in that scenario? Can you signup using your development account and then later switch to production?

@malfree
Copy link

malfree commented Apr 16, 2021

Our recommendation is to use your prod account to test with test products. We don't have a way to switch accounts. However, be aware throttling limits are per account and any test usage will impact your product usage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants