Authenticating AppSync mutation using AWS Cognito User pool on Graphql playground - graphql

A very basic scenario where I want to test an AppSync mutation on Graphql playground which was working fine with API key authentication.
I have attached an additional authorization provider besides the API key authentication.
Mutation:
type Mutation {
createPitch(gameID: ID!, pitchID: Int!, pitchEvent: PitchInput!): Pitch
#aws_api_key
predictPitch(userID: String!, gamePitchID: String!, prediction: PredictionInput): Prediction
#aws_cognito_user_pools
}
Invoking predictPitch mutation on graphql playground:
mutation PredictPitch($prediction:PredictionInput) {
predictPitch(userID: "12345", gamePitchID: "29fb2xx-xxxxx-xxxxx-1",
prediction: $prediction ) {
gameID
gamePitchID
}
}
query variables:
{
"prediction": {
"gameID": "29",
"hitterGuess": "Miss",
"pitcherGuess": "Fastball"
}
}
Headers:
{
"X-API-KEY": "da2-o6fs2lq47vbehexxxxxxxx",
"Authorization": "Bearer xxxx-the-pretty-long-jwt-token-from-cognito login"
}
I have tried Authorization header alone and in conjunction with x-api-key.
Nothing worked so far. I am pretty sure I am missing a very tiny bit.
{
"error": {
"errors": [
{
"errorType": "UnauthorizedException",
"message": "Valid authorization header not provided."
}
]
}
}
NOTE: The JWT token AccessToken is generated via aws-cli
aws cognito-idp admin-initiate-auth.

I had to add #aws_cognito_user_pools on type Prediction along with my mutation.
type Prediction #aws_cognito_user_pools {
gameID
gamePitchID
}
Also, from Cognito I had to use idToken like so:
{
"Authorization": "xxxxxxxxxx"
}
Do notice the Bearer is missing.

Related

Authorization error when trying to call Amplify Graphql Mutation with Function

I am trying to call a lambda function using GraphQL mutation in Amplify. Unfortunately I am getting Unauthorized error when I call it.
This is the schema:
type Mutation {
createPaymentIntent(amount: Int!, currency: Currency!): PaymentIntent! #function(name: "CreatePaymentIntent-${env}")
createPaypalPayment(amount: Int!, currency: Currency!): PaypalPayment! #function(name: "StartPaypalPayment-${env}")
}
type PaymentIntent {
clientSecret: String!
}
type PaypalPayment {
value: String!
}
When I call it using IAM it is working fine. But with Cognito pool (after signing in) it throws error. I also tried to turn off auth for the full api (but didn't help):
input AMPLIFY {
globalAuthRule: AuthRule = { allow: public }
}

Empty data in AWS AppSync GraphQL subscription event

I have an application that uses a GraphQL API, provided by the AWS AppSync service. It uses GraphQL subscriptions to send messages between different clients in near real time. There is a mutation pushItems that's configured with a resolver, which has a 'none' data source and forwards the request data unmodified to the subscription onItemChange.
The app hasn't been used for a couple of years, and now when I attempt to trigger a subscription event, I get an error on the subscribed client. Previously this worked without issues.
{
"data": {
"onItemChange": null
},
"errors": [
{
"message": "Cannot return null for non-nullable type: 'ID' within parent 'Item' (/onItemChange/id)",
"path": [
"onItemChange",
"id"
]
}
]
}
The error message suggests that the property id within the Item object is null, however when I send a mutation from the AWS AppSync web console with a hard-coded string for the item ID, I still get the same issue, even though the mutation response contains the correct data that should be forwarded to the subscribed client.
I've created a minimal configuration in AWS AppSync to reproduce the issue, which is detailed below. Is it possible that the AppSync service has changed the way it handles subscription data in the last few years?
GraphQL schema
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
type Query {
getItem(id: ID!): Item
}
type Mutation {
pushItems(
items: [ItemInput]
): [Item]}
type Subscription {
onItemChange: Item
#aws_subscribe(
mutations: [
"pushItems"
]
)
}
type Item {
id: ID!
}
input ItemInput {
id: ID!
}
Resolver mappings for mutation pushItems
Request:
{
"version" : "2017-02-28",
"payload": $util.toJson($context.arguments.items)
}
Response:
$util.toJson($context.result)
Example queries
The following queries can be used to reproduce the issue in the AWS AppSync web console. First, subscribe to onItemChange:
subscription MySubscription {
onItemChange {
id
}
}
Then (in a different browser tab) send some data to pushItems:
mutation MyMutation {
pushItems(items: [{id: "foo"}]) {
id
}
}
You are returning Set of items in the mutation so you should update subscription return type to [Item]
type Subscription {
onItemChange: [Item] <--- HERE
#aws_subscribe(mutations: ["pushItems"])
}

Updating meta fields in Shopify with GrapQL

I've never used GraphQL before so I am really lacking knowledge on how to go about this. I'm wanting to update product meta fields on Shopify and it appears this is the only way. What I've done so far is really fumbling...
My JSON is:
{
"input": {
"id": "gid://shopify/Product/749521178847",
"metafields": [
{
"id": "gid://shopify/Metafield/2223333",
"value": "Training Grounds"
}
]
}
}
I've minified this to:
{"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
And am then using an HTTP request to:
https://MYSTORE.myshopify.com/api/2021-10/graphql.json?query={"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
I get the error:
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
I don't know if any of this is correct. If it is, I don't know if ?query= is the right variable to pass it through on.
I recommend you start using Postman, thunder client, or similar to write your graphql queries first, you will learn a lot about how graphql works and the error msgs will be a lot more useful.
To easily connect with Shopify on this stage, go to a store and create a private app, now you can use this for authenticating your API calls.
After that the Shopify graphql works on POST, you can't write your request on GET mode.
It needs to be a POST and you are missing type of operation mutation in this case and what it is.
Postman has https://www.postman.com/lively-moon-541169/workspace/purego-apis/example/16545848-bf0d1589-09b1-4ec6-ba63-a65a56b500eb examples of how to do the calls which can help you.
Also you can check GraphiQL app on shopify to test all the queries before making the programmatic queries
Updating an existing metafield:
mutation {
metafieldsSet(metafields: [
{namespace: "YOURNAMESPACE", ownerId: "gid://shopify/Customer/CUSTOMER_ID", type: "single_line_text_field", key: "YOURKEY", value: "THIS IS NEW VALUE"}
]) {
metafields {
key
value
}
userErrors {
field
message
}
}
}
Creating new metafield:
mutation {
customerUpdate(input: {
id: "gid://shopify/Customer/CUSTOMER_ID",
metafields: [
{key: "newkey", value: "some value", type: "single_line_text_field", namespace: "some namespace"},
]
}) {
userErrors {
field
message
}
}
}

How to document errors in graphql?

type Query {
"""
ErrorCode: EMAIL_DUPLICATED
type EmailDuplicatedError {
email: String!
source: UserSource!
}
enum UserSource {
Google
Facebook
Github
}
"""
register(email: String!, password: String!): AccessToken!
}
"""
The AccessToken scalar type is a string of 16 characters.
"""
scalar AccessToken
Hope you can get what I mean through the above schema. I'd like to know if there is any code generator can support errors documented this way, so I can reduce the code I write on both client and server side.
I don't want to define errors like the following
type Query {
register(email: String!, password: String!): RegisterResponse
}
type RegisterResponse {
accessToken: AccessToken
error: EmailDuplicatedError
}
type EmailDuplicatedError {
email: String!
source: UserSource!
}
enum UserSource {
Google
Facebook
Github
}
"""
The AccessToken scalar type is a string of 16 characters.
"""
scalar AccessToken
Because I'd like errors to be responded in errors field, and api only shows what you can get when you succeeded.
Thank you for your time reading this post.
There's some ways to do error handling with GraphQL, I'll recommend you two:
Using response extensions:
GraphQL JSON response.error has a field called extensions, you can use this to set a code field like:
{
"error": {
"errors": [
{
"message": "example",
"extensions": {
"code": "YOUR CODE"
}
}
]
}
}
Using unions:
There is an medium post by Sasha Solomon that talks about that:
https://sachee.medium.com/200-ok-error-handling-in-graphql-7ec869aec9bc
Using the examples in this post, the way to handle graphql errors with unions is like this:
type User {
id: ID!
name: String
}
type Suspended {
reason: String
}
type IsBlocked {
message: String
blockedByUser: User
}
type UnavailableInCountry {
countryCode: Int
message: String
}
"User, or reason we can't get one normally"
union UserResult = User | IsBlocked | Suspended
type Query {
user: UserResult!
}

Strapi graphql mutation

I'm using strapi as a headless CMS
I've created a Customer content type and I've installed the graphql plugin.
I'm trying to create a mutation in the graphql playground to create a new Customer
mutation createCustomer($username: String!, $email: String, $password: String){
createCustomer(username: $username, email: $email, password: $password){
_id username email password
}
}
I'm passing the username etc in the query variables
{ "username": "user1" }
{ "email": "User1#test.com" }
{"password":"123456"}
I'm getting the error
"message": "Unknown argument \"username\" on field \"createCustomer\" of type \"Mutation\".",
If I look in the Docs the it looks like.
How can I write a mutation to create a new Customer
That error indicates that are missing the reference to Customer type in the Query component of the Mutation.
Also, I believe you are missing "input:" & "data:". I know that these are required when using createUser.
By example:
mutation createCustomer($username: String!, $email: String, $password: String) {
createCustomer(
input: { data: { username: $username, email: $email, password: $password } }
) {
customer {
id
username
email
password
}
}
}

Resources