使用 AWS amplify 和 grahql 创建新用户时出现“未经授权”错误

问题描述 投票:0回答:4

所以我认为这个问题来自于我不太了解 AWS cognito 用户池和 graphql 模式中的身份验证规则之间的关系。

当我运行下面的代码时,我收到消息“未授权访问 User 类型上的 createUser”。

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);

其他相关代码是我的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')
);

以及 User 对象的架构定义:

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
}

最终,我正在尝试制作类似于此示例的东西。我尝试阅读 aws amplify 文档,但无法正确理解身份验证如何影响 graphql 操作。

reactjs amazon-web-services graphql aws-amplify
4个回答
10
投票

我刚刚花了几个小时来解决同样的问题。对我来说,我必须在 graphql 请求上指定 authMode。

而不是做这样的事情:

await API.graphql(graphqlOperation(createFamily, {input: family}))

我必须使用这个:

await API.graphql({
        query: createFamily,
        variables: {input: family},
        authMode: 'AMAZON_COGNITO_USER_POOLS'
      })

我确实尝试了用户密码的解决方案。但是,我对架构所做的任何操作都无效(包括按指示添加@aws_cognito_user_pools)。

不幸的是,Amplify 文档并没有很好地记录该过程。我希望这可以帮助其他人节省一些时间。


1
投票

非常确定解决方案是将 @aws_cognito_user_pools 添加到用户的架构定义中。我还更改了它以允许所有者做任何他们想做的事情,但在他们无法查询之前。

type User 
  @model 
  @auth(rules: [{ allow: owner}])
  @aws_cognito_user_pools {
  id: ID!
  username: String!
  conversations: [ConvoLink] @connection(name: "UserLinks")
  messages: [Message] @connection(name: "UserMessages")
    createdAt: String
    updatedAt: String
}

1
投票

问题是模型的auth模式与配置不匹配。

如果您的模型不是“公开”的(任何拥有 API 密钥的人都可以使用),那么您需要使用正确的模式来授权请求。

如果您使用放大授权模块,您可能会在

aws_cognito_user_pools
中进行中继。 在这种情况下,您应该指定“Cognito 用户池”作为默认授权方法。

要更改 API 授权默认模式,您需要转到 aws amplify 的数据建模工具,从那里(标题下方)有“管理 API 授权模式和密钥”的链接。

当使用“Cognito 用户池”作为默认授权方法时,您可以像往常一样正确使用 API 来获取私有方法。 这也解决了我的订阅问题。


0
投票

使用Amplify 6时,遇到此问题时可能有几个问题需要解决。

(1)

首先,如果您的数据可通过角色继承访问(即 {allow: groups, groups: ["Admin"] } 或类似),您应该考虑将

src/amplifyconfiguration.json
中的 appsync 身份验证类型设置为:
"aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS"
而不是
"aws_appsync_authenticationType": "API_KEY" 
.

(2)

然后,您可能会遇到与

No current user
相关的问题。这是与您的认知身份池没有必要的授权相关的第二步。然后,您可能需要从服务 authRole 修改 IAM 规则。然后,您需要转到
IAM -> Roles -> amplify-<xxx>-authRole
并单击选项卡
Tust relationships
并使用以下内容授权您的用户池:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "cognito-identity.amazonaws.com:aud": "<YOUR_IDENTITY_POOL_ID>"
                },
                "ForAnyValue:StringLike": {
                    "cognito-identity.amazonaws.com:amr": "authenticated"
                }
            }
        }
    ]
}

您必须将

<YOUR_IDENTITY_POOL_ID>
替换为可在
Amazon Cognito -> Identity pools
中找到的身份池 ID。

(3)

之后,无论您相信与否,您仍然可能会遇到

UnauthorizedException
类型的问题,这可能是因为您与Auth相关的AWS AppSync服务没有正确的
Additional authorization mode
。然后,您必须转到
AWS AppSync -> Settings (of your AppSync API)
,然后转到
Additional authorization modes
,并使用正确的授权模式标识符添加各自的 Amazon Cognito 用户池。

最后,您可以与 graphql CLI 进行通信!

© www.soinside.com 2019 - 2024. All rights reserved.