graphql-dotnet / graphql-client

A GraphQL Client for .NET Standard
MIT License
619 stars 131 forks source link

Using GraphQL client to access AWS AppSync protected by IAM security #121

Open NeilBostrom opened 5 years ago

NeilBostrom commented 5 years ago

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.

deinok commented 4 years ago

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

NeilBostrom commented 4 years ago

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

asanjeevak commented 3 years ago

@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....

NeilBostrom commented 3 years ago

@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.

asanjeevak commented 3 years ago

@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.

NeilBostrom commented 3 years ago

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.

asanjeevak commented 3 years ago

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
NeilBostrom commented 3 years ago

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?

asanjeevak commented 3 years ago

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

NeilBostrom commented 3 years ago

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.

asanjeevak commented 3 years ago

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" } ] }

NeilBostrom commented 3 years ago

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.

asanjeevak commented 3 years ago

@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?

NeilBostrom commented 3 years ago

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.

hasnainv commented 2 years ago

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

hasnainv commented 2 years ago

@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)?

NeilBostrom commented 2 years ago

@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.

menkari commented 1 year ago

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