So I think this issue comes from me not quite understanding the relationship between AWS cognito user pools and the auth rules in a graphql schema.
When I run the code below, I get the message "Not Authorized to access createUser on type User".
import React from 'react';
import { Auth, API, graphqlOperation } from 'aws-amplify';
import { withAuthenticator } from "@aws-amplify/ui-react";
// This was created automatically from the schema by aws amplify
const CreateUser = /* GraphQL */ `
mutation CreateUser(
$input: CreateUserInput!
$condition: ModelUserConditionInput
) {
createUser(input: $input, condition: $condition) {
id
username
conversations {
items {
id
convoLinkUserId
convoLinkConversationId
createdAt
updatedAt
}
nextToken
}
messages {
items {
id
authorId
content
messageConversationId
createdAt
updatedAt
}
nextToken
}
createdAt
updatedAt
}
}
`;
async function signIn(username, password) {
try {
const user = await Auth.signIn(username, password);
const { attributes } = user;
console.log("User", attributes)
return user
} catch (error) {
console.log('error signing in', error);
}
}
async function createUser(id) {
// creating a new user in the dynamodb table
try {
const newUser = {input: {username: id, id}}
console.log("Creating new user", newUser)
await API.graphql(graphqlOperation(CreateUser, newUser))
} catch (err) {
console.log('Error creating user! :', err)
}
}
async function testApiCalls() {
await signIn("[email protected]", "notarealpassword123") // runs successfully
await createUser("[email protected]") // where the error happens
}
function App() {
testApiCalls()
return (
<div className="App">
Hello
</div>
);
}
export default withAuthenticator(App);
Other relevant code would be my index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import Amplify, { Auth } from 'aws-amplify';
import AWSAppSyncClient from 'aws-appsync'
import aws_config from './aws-exports';
import { ApolloProvider } from '@apollo/client';
Amplify.configure(aws_config);
aws_config.graphql_headers = async () => { const currentSession = await Auth.currentSession(); return { Authorization: currentSession.getIdToken().getJwtToken() }; };
const client = new AWSAppSyncClient({
url: aws_config.aws_appsync_graphqlEndpoint,
region: aws_config.aws_appsync_region,
auth: {
type: aws_config.aws_appsync_authenticationType, // AMAZON_COGNITO_USER_POOLS
jwtToken: async () => (await Auth.currentSession()).idToken.jwtToken
}
});
const WithProvider = () => (
<ApolloProvider client={client}>
<App/>
</ApolloProvider>
)
ReactDOM.render(
<WithProvider/>,
document.getElementById('root')
);
And the schema definition for the User object:
type User
@model
@auth(rules: [{ allow: owner, ownerField: "id", queries: null }]) {
id: ID!
username: String!
conversations: [ConvoLink] @connection(name: "UserLinks")
messages: [Message] @connection(name: "UserMessages")
createdAt: String
updatedAt: String
}
Ultimately, I'm trying to make something similar to this example. I've tried reading the aws amplify docs but haven't been able to properly understand how the graphql operations are effected by the authentication.
I'm pretty sure that the solution was adding @aws_cognito_user_pools to the schema definition for User. I also changed it to allow the owner to do whatever they want, but before they were unable to query.