Skip to content

getAmplifyDataClientConfig() fails to check Amplify data variables when API name is definedΒ #2320

@lengieng

Description

@lengieng

Environment information

System:
  OS: Windows 11 10.0.26100
  CPU: (12) x64 13th Gen Intel(R) Core(TM) i5-1335U
  Memory: 2.08 GB / 15.72 GB
Binaries:
  Node: 22.2.0 - C:\Program Files\nodejs\node.EXE
  Yarn: 1.22.22 - ~\AppData\Roaming\npm\yarn.CMD
  npm: 10.9.1 - C:\Program Files\nodejs\npm.CMD
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/auth-construct: 1.5.1
  @aws-amplify/backend: 1.9.0
  @aws-amplify/backend-auth: 1.4.2
  @aws-amplify/backend-cli: 1.4.3
  @aws-amplify/backend-data: 1.2.2
  @aws-amplify/backend-deployer: 1.1.11
  @aws-amplify/backend-function: 1.9.0
  @aws-amplify/backend-output-schemas: 1.4.0
  @aws-amplify/backend-output-storage: 1.1.4
  @aws-amplify/backend-secret: 1.1.5
  @aws-amplify/backend-storage: 1.2.4
  @aws-amplify/cli-core: 1.2.1
  @aws-amplify/client-config: 1.5.3
  @aws-amplify/deployed-backend-client: 1.4.2
  @aws-amplify/form-generator: 1.0.3
  @aws-amplify/model-generator: 1.0.9
  @aws-amplify/platform-core: 1.3.0
  @aws-amplify/plugin-types: 1.6.0
  @aws-amplify/sandbox: 1.2.7
  @aws-amplify/schema-generator: 1.2.6
  aws-amplify: 6.10.2
  aws-cdk: 2.172.0
  aws-cdk-lib: 2.172.0
  typescript: 5.6.2
No AWS environment variables
No CDK environment variables

Describe the bug

The doc shows an example of how to use defineAuth and defineFunction to create Cognito post confirmation Lambda trigger. Another related section is grant Lambda function access to API.

When name is given in the defineData(), the generated env that start with the AMPLIFY_DATA prefix are replaced with the given name.

export const data = defineData({
  name: 'CoolName',
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'apiKey',
    apiKeyAuthorizationMode: {
      expiresInDays: 90,
    },
  },
})

Without name given (default):

AMPLIFY_DATA_GRAPHQL_ENDPOINT 
AMPLIFY_DATA_MODEL_INTROSPECTION_SCHEMA_BUCKET_NAME
AMPLIFY_DATA_MODEL_INTROSPECTION_SCHEMA_KEY

With name given:

COOL_NAME_GRAPHQL_ENDPOINT 
COOL_NAME_MODEL_INTROSPECTION_SCHEMA_BUCKET_NAME
COOL_NAME_MODEL_INTROSPECTION_SCHEMA_KEY

In this case, in the amplify/auth/post-confirmation/handler.ts, this line const { resourceConfig, libraryOptions } = await getAmplifyDataClientConfig(env) fails to generate the resourceConfig because the isDataClientEnv(env) used in the getAmplifyDataClientConfig() always returns false.

Code below taken from here in the recent pull commit 2224.

const isDataClientEnv = (env: unknown): env is DataClientEnv => {
  return (
    env !== null &&
    typeof env === 'object' &&
    'AMPLIFY_DATA_MODEL_INTROSPECTION_SCHEMA_BUCKET_NAME' in env && // <-- FAIL
    'AMPLIFY_DATA_MODEL_INTROSPECTION_SCHEMA_KEY' in env &&  // <-- FAIL
    'AWS_ACCESS_KEY_ID' in env &&
    'AWS_SECRET_ACCESS_KEY' in env &&
    'AWS_SESSION_TOKEN' in env &&
    'AWS_REGION' in env &&
    'AMPLIFY_DATA_GRAPHQL_ENDPOINT' in env && // <-- FAIL
    typeof env.AMPLIFY_DATA_MODEL_INTROSPECTION_SCHEMA_BUCKET_NAME ===
      'string' && // <-- FAIL
    typeof env.AMPLIFY_DATA_MODEL_INTROSPECTION_SCHEMA_KEY === 'string' && // <-- FAIL
    typeof env.AWS_ACCESS_KEY_ID === 'string' &&
    typeof env.AWS_SECRET_ACCESS_KEY === 'string' &&
    typeof env.AWS_SESSION_TOKEN === 'string' &&
    typeof env.AWS_REGION === 'string' &&
    typeof env.AMPLIFY_DATA_GRAPHQL_ENDPOINT === 'string' // <-- FAIL
  )
}

Reproduction steps

Follow the example in the doc with an additional step to add the name to defineData().

  1. Give the API a name in defineData()
// amplify/data/resource.ts
import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
import { postConfirmation } from "../auth/post-confirmation/resource";

const schema = a
  .schema({
    UserProfile: a
      .model({
        email: a.string(),
        profileOwner: a.string(),
      })
      .authorization((allow) => [
        allow.ownerDefinedIn("profileOwner"),
      ]),
  })
  .authorization((allow) => [allow.resource(postConfirmation)]);
export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  name: "CoolName", // Give the API a name
  schema,
  authorizationModes: {
    defaultAuthorizationMode: "apiKey",
    apiKeyAuthorizationMode: {
      expiresInDays: 30,
    },
  },
});
  1. Create post-confirmation resource file amplify/auth/post-confirmation/resource.ts:
// amplify/auth/post-confirmation/resource.ts
import { defineFunction } from '@aws-amplify/backend';

export const postConfirmation = defineFunction({
  name: 'post-confirmation',
});
  1. Create post-confirmation handler file amplify/auth/post-confirmation/handler.ts:
// amplify/auth/post-confirmation/handler.ts
import type { PostConfirmationTriggerHandler } from "aws-lambda";
import { type Schema } from "../../data/resource";
import { Amplify } from "aws-amplify";
import { generateClient } from "aws-amplify/data";
import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime';
import { env } from "$amplify/env/post-confirmation";

const { resourceConfig, libraryOptions } = await getAmplifyDataClientConfig(
  env
);

Amplify.configure(resourceConfig, libraryOptions);

const client = generateClient<Schema>();

export const handler: PostConfirmationTriggerHandler = async (event) => {
  await client.models.UserProfile.create({
      email: event.request.userAttributes.email,
      profileOwner: `${event.request.userAttributes.sub}::${event.userName}`,
  });

  return event;
};
  1. Set trigger in amplify/auth/resource.ts
// amplify/auth/resource.ts
import { defineAuth } from '@aws-amplify/backend';
import { postConfirmation } from './post-confirmation/resource';

export const auth = defineAuth({
  loginWith: {
    email: true,
  },
  triggers: {
    postConfirmation
  }
});

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdataIssue pertaining to Amplify Data

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions