Search code examples
graphqlserverlessaws-amplifyaws-appsyncfederated-identity

Developer authenticated identities federated via an Identity Pool cannot make AppSync calls in Amplify project


Currently, I'm authenticating Linkedin users and calling GetOpenIdTokenForDeveloperIdentity and GetCredentialsForIdentity in a Lambda, and signing in those users with Auth.federatedSignIn(), I am able to retrieve the current authenticated user and credentials.

Using Amplify's APIClass or AWSAppSyncClient, however, I cannot get these users to make GraphQL calls through AppSync, which is configured to authorize Cognito User Pool and AWS IAM users. The Cognito User Pool users have no problem making AppSync calls when the authentication type is changed accordingly.

I have tried each of the following for the federated users:

API.graphql({
  query: queries.getUserProfile,
  variables: {
    input: {
      email,
    }
  },
  authMode: 'AWS_IAM'
})

const client = new AWSAppSyncClient({
  url: process.env.GRAPHQL_ENDPOINT,
  region: process.env.AWS_REGION,
  auth: {
    type: AUTH_TYPE.AWS_IAM,
    credentials: async () => Auth.currentCredentials(),
  },
  disableOffline: true,
});

client.query({
  query: gql(queries.getUserProfile),
  variables: {
    input: {
      email,
    },
  },
  fetchPolicy: 'no-cache',
})

The Identity Pool is provisioned through Serverless resources/CloudFormation templates, and I've set the trust relationship and authenticated role like so:

  ProjectAuthRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Federated: "cognito-identity.amazonaws.com"
            Action:
              - "sts:AssumeRoleWithWebIdentity"
            Condition:
              StringEquals:
                "cognito-identity.amazonaws.com:aud":
                  - Ref: ProjectIdentityPool
              ForAnyValue:StringLike:
                "cognito-identity.amazonaws.com:amr": authenticated
  AuthPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - mobileanalytics:PutEvents
              - cognito-sync:*
              - cognito-identity:*
            Resource:
              - "*"
          - Effect: Allow
            Action:
              - appsync:GraphQL
            Resource:
              - "*"
      Roles:
        - Ref: ProjectAuthRole

I have been able to make GraphQL calls by adding the @aws_iam schema directive to every type and input definition, but it sounds like this shouldn't even be necessary, as the authorization should be happening AWS AppSync GraphQL API level.

Any ideas where else I might have forgotten to configure?


Solution

  • It looks like the issue was the additionalAuthenticationProviders in our serverless-appsync-plugin YAML file.

    My understanding is that schema-level directives must be applied to type definitions in one's schema if you want additional authentication providers (in our case, AWS_IAM) to have access alongside the default authentication provider (in our case, AMAZON_COGNITO_USER_POOLS).

    Source for further details: https://docs.aws.amazon.com/appsync/latest/devguide/security.html#using-additional-authorization-modes