graphql-client icon indicating copy to clipboard operation
graphql-client copied to clipboard

Using GraphQL client to access AWS AppSync protected by IAM security

Open NeilBostrom opened this issue 5 years ago • 18 comments

This doesn't really live here but wanted to log something for anyone that comes looking for a solution to using this client with AWS AppSync. Feel free to close this.

I have a gist available that shows using the built-in AWS4Signer to access an AppSync GraphQL endpoint protected by AWS_IAM authorization.

NeilBostrom avatar May 31 '19 08:05 NeilBostrom

Hey, @NeilBostrom thanks for this. Could I get your code and put it in the example sections of this lib as an AWS AppSync?

deinok avatar Sep 16 '19 02:09 deinok

Oh please do! That would be great. Let me know if you need anything more than the Gist.

NeilBostrom avatar Sep 16 '19 11:09 NeilBostrom

@NeilBostrom Can you share a working example how to access appsync API protected by IAM security, i checked the gist, looks like its incomplete.. do you have any library for using or please share an example....

asanjeevak avatar Dec 03 '20 17:12 asanjeevak

@asanjeevak I've updated my gist to the latest version of the client libraries. I've got a small sample app available at: https://s3.eu-west-1.amazonaws.com/com.ipresent.dev.cloudformation/SampleApp.zip. I've not got any IAM authenticated services running to test the changes with but if you can try them, let me know if you get any issues with it.

NeilBostrom avatar Dec 04 '20 10:12 NeilBostrom

@asanjeevak I've updated my gist to the latest version of the client libraries. I've got a small sample app available at: https://s3.eu-west-1.amazonaws.com/com.ipresent.dev.cloudformation/SampleApp.zip. I've not got any IAM authenticated services running to test the changes with but if you can try them, let me know if you get any issues with it.

Hi Neil, I tried this sample looks like all the methods and properties in AmazonHttpRequestSigning class are left with "NotImplementedException()" and when i actually run the application it throws the same with not implemented message.

I am trying to test the app sync mutations with iam authentication.

asanjeevak avatar Dec 04 '20 11:12 asanjeevak

Are you able to tell me which property / method is throwing the NotImplementedException? I've stubbed off all the props / methods that were not being used at the time, this may change with different calls as my example was only a GET. Let me know the items its dying on, I can just implement them to get you running.

NeilBostrom avatar Dec 04 '20 12:12 NeilBostrom

There is a region #region Not Implemented of which all are not implemeted only... I am trying a mutation call #region Not Implemented

        public string RequestName => throw new NotImplementedException();

        public IDictionary<string, string> Parameters => throw new NotImplementedException();

        public ParameterCollection ParameterCollection => throw new NotImplementedException();

        public bool SetContentFromParameters { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public long OriginalStreamPosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public string ServiceName => throw new NotImplementedException();

        public AmazonWebServiceRequest OriginalRequest => throw new NotImplementedException();

        public string HostPrefix { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public bool Suppress404Exceptions { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public AWS4SigningResult AWS4SignerResult { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public string CanonicalResourcePrefix { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public bool UseSigV4 { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public void AddPathResource(string key, string value) => throw new NotImplementedException();
        public void AddSubResource(string subResource) => throw new NotImplementedException();
        public void AddSubResource(string subResource, string value) => throw new NotImplementedException();
        public string ComputeContentStreamHash() => throw new NotImplementedException();
        public string GetHeaderValue(string headerName) => throw new NotImplementedException();
        public bool HasRequestBody() => throw new NotImplementedException();
        public bool IsRequestStreamRewindable() => throw new NotImplementedException();
        public bool MayContainRequestBody() => throw new NotImplementedException();

        #endregion

asanjeevak avatar Dec 04 '20 12:12 asanjeevak

If you debug the program, are you able to tell me which property was the source of the exception? Not all the methods need to be implemented for the class to work for signing.

Are you able to provide me with a sample that crashes so I can try it here otherwise?

NeilBostrom avatar Dec 04 '20 12:12 NeilBostrom

It failed on multiple properties... I have to run again to check.... if it works faster at your side please check... thanks for your support

asanjeevak avatar Dec 04 '20 12:12 asanjeevak

I'm not able to test it here as I don't have a GraphQL service that I can mutate against.

If you can list all the property names it failed on, I can implement those for you.

NeilBostrom avatar Dec 04 '20 12:12 NeilBostrom

I'm not able to test it here as I don't have a GraphQL service that I can mutate against.

If you can list all the property names it failed on, I can implement those for you.

I see the below error today with the updated sample you provided. { "errors" : [ { "errorType" : "BadRequestException", "message" : "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'POST\n/graphql\n\nhost:xxxxxxx.amazonaws.com\nuser-agent:GraphQL.Client/3.2.0.0 GraphQL.Client/3.2.0.0\nx-amz-content-sha256:84b8fa994c9a620cd047980bd03658bd966b5f2ee120cd3c70486079ad3306e7\nx-amz-date:20201204T122601Z\n\nhost;user-agent;x-amz-content-sha256;x-amz-date\n84b8fa994c9a620cd047980bd03658bd966b5f2ee120cd3c70486079ad3306e7'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20201204T122601Z\n20201204/ap-south-1/appsync/aws4_request\n83d72a308d8048bf0f1fdceab3fbffbb62ad6d1729611005d1a9e4509bd43f1b'\n" } ] }

asanjeevak avatar Dec 04 '20 12:12 asanjeevak

Looks like an issue with the signing request. Not sure I can help a huge amount as I can't reproduce the issue here.

Sorry I can't be more help.

NeilBostrom avatar Dec 04 '20 12:12 NeilBostrom

@NeilBostrom Quick question on the IAM authentication... I observe we are passing access_key, access_secret and a short lived token, who takes care of refreshing this short lived token?

asanjeevak avatar Dec 04 '20 13:12 asanjeevak

These session tokens would be requested when required. You can use STS to request these session tokens: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html.

Generating a session token would usually be done on your authenticated server and passed to your authenticated clients on request.

NeilBostrom avatar Dec 04 '20 13:12 NeilBostrom

@NeilBostrom Thank you so much for the gist and the zip! Your package saved days worth of effort on my end!

hasnainv avatar Nov 02 '21 09:11 hasnainv

@NeilBostrom Was wondering if you have any thoughts on this I'm able to make requests for an S3 object using:

const string IdentityPool = "us-east-1:xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
CognitoAWSCredentials awsGuestCredentials = new CognitoAWSCredentials(IdentityPool, Region);
AmazonS3Client S3Client = new AmazonS3Client(awsGuestCredentials, "us-east-1");
string S3URL = S3Client.GetPreSignedURL(request);

Do you happen to know of a way to make graphql queries using the same awsGuestCredentials (i.e. using a Cognito user)?

hasnainv avatar Nov 09 '21 13:11 hasnainv

@hasnainv Afraid I don't. I've not used Cognito before. If you can get an accesskey, secretkey and session token from the credentials class then you can use my gist.

NeilBostrom avatar Nov 10 '21 09:11 NeilBostrom

I'm not able to test it here as I don't have a GraphQL service that I can mutate against. If you can list all the property names it failed on, I can implement those for you.

I see the below error today with the updated sample you provided. { "errors" : [ { "errorType" : "BadRequestException", "message" : "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'POST\n/graphql\n\nhost:xxxxxxx.amazonaws.com\nuser-agent:GraphQL.Client/3.2.0.0 GraphQL.Client/3.2.0.0\nx-amz-content-sha256:84b8fa994c9a620cd047980bd03658bd966b5f2ee120cd3c70486079ad3306e7\nx-amz-date:20201204T122601Z\n\nhost;user-agent;x-amz-content-sha256;x-amz-date\n84b8fa994c9a620cd047980bd03658bd966b5f2ee120cd3c70486079ad3306e7'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20201204T122601Z\n20201204/ap-south-1/appsync/aws4_request\n83d72a308d8048bf0f1fdceab3fbffbb62ad6d1729611005d1a9e4509bd43f1b'\n" } ] }

@asanjeevak Did you ever figure this out? I've just come across this and running into the same problem - Thanks

menkari avatar Apr 18 '23 17:04 menkari