0

I created a AWS AppSync based GraphQL endpoint, which can be accessed by IAM users only. Now I want to consume this endpoint in C#.net. How can I access it via C#.Net.

I already tried APIKey authentication with GraphQL client library. But, not sure how to access same endpoint with AWS SDK.

Debsdoon
  • 51
  • 7

2 Answers2

1

There is no SDK available for AWS AppSync - Data Plane API in AWS SDK for .NET. However there is an SDK for Control Plane Operations.

In order to use IAM based authorization for calls to AWS AppSync, you need to have valid Access Key and Secret Access Key and sign the HTTP requests sent to AWS AppSync using AWS SigV4 algorithm. You can take a look at the signing algorithm here.

You can use the Access and Secret Access Keys of an IAM user in your AWS account or you can use Amazon Cognito Identity Pools to retrieve short lived AWS Credentials that can be used to sign the HTTP request sent to AWS AppSync.

You can take a look at our implementation on iOS and Android for reference.

Karthikeyan
  • 1,411
  • 1
  • 13
  • 13
0

In case anyone needs it, posting the code below. Pass in the query (or mutation) as string and variables as dictionary.

using Amazon.Runtime.Internal.Auth;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Amazon;
using Amazon.Runtime;
using Amazon.AppSync;
using Amazon.Runtime.Internal;
using Amazon.Util;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Amazon.Lambda.Core;

public class GraphQLOperations
{
  private static readonly string GRAPHQL_ENDPOINT = Environment.GetEnvironmentVariable("API_XXXXXX_GRAPHQLAPIENDPOINTOUTPUT"); // Amplify passes this to my lambda
  private static readonly string AWS_REGION = Environment.GetEnvironmentVariable("AWS_REGION") ?? "us-west-2";

  private static async Task<JObject> RunGraphql(string query, Dictionary<string, object> variables)
  {
    var immutableCredentials = FallbackCredentialsFactory.GetCredentials().GetCredentials();
    immutableCredentials = new EnvironmentVariablesAWSCredentials().GetCredentials();

    var endpoint = new Uri(GRAPHQL_ENDPOINT);

    // Construct httpRequestMessage - set headers here. Some headers related to Content will be auto added by .net library
    var jsonPayload = JsonConvert.SerializeObject(new { query, variables });
    var requestContent = new StringContent(jsonPayload, Encoding.ASCII, "application/json");
    var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint)
    {
      Content = requestContent
    };

    httpRequestMessage.Headers.Add(HeaderKeys.XAmzSecurityTokenHeader, immutableCredentials.Token);
    httpRequestMessage.Headers.Add(HeaderKeys.HostHeader, endpoint.Host);

    // Construct AWS request object
    var rawBytes = Encoding.ASCII.GetBytes(await requestContent.ReadAsStringAsync());
    var awsRequest = new DefaultRequest(new AmazonAppSyncRequest(), "appsync")
    {
      HttpMethod = "POST",
      Endpoint = endpoint,
      Content = rawBytes,
      AlternateEndpoint = RegionEndpoint.GetBySystemName(AWS_REGION)
    };

    // Add all headers from httpRequestMessage to AWS request object
    foreach (var header in httpRequestMessage.Headers.Concat(httpRequestMessage.Content.Headers))
    {
      awsRequest.Headers[header.Key] = string.Join(", ", header.Value);
    }

    var signer = new AWS4Signer();
    signer.Sign(awsRequest, new AmazonAppSyncConfig(), null, immutableCredentials);

    var httpClient = new HttpClient();

    // add the signer's authorization+other headers to httpRequestMessage
    foreach (var header in awsRequest.Headers)
    {
      if (header.Key.ToLowerInvariant() != HeaderKeys.ContentTypeHeader.ToLowerInvariant() &&
          header.Key.ToLowerInvariant() != HeaderKeys.ContentLengthHeader.ToLowerInvariant() &&
          header.Key.ToLowerInvariant() != HeaderKeys.XAmzSecurityTokenHeader.ToLowerInvariant() &&
          header.Key.ToLowerInvariant() != HeaderKeys.HostHeader.ToLowerInvariant())
      {
        httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value);
      }
    }

    var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
    var content = await httpResponseMessage.Content.ReadAsStringAsync();

    var response = JsonConvert.DeserializeObject<JObject>(content);

    if (response["errors"] != null)
    {
      throw new Exception(JsonConvert.SerializeObject(response["errors"]));
    }

    return response;
  }
}
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 09 '23 at 18:09