---
title: "Custom data access using Lambda functions"
section: "build-a-backend/data/customize-authz"
platforms: ["android", "angular", "flutter", "javascript", "nextjs", "react", "react-native", "swift", "vue"]
gen: 2
last-updated: "2026-03-25T17:40:00.000Z"
url: "https://docs.amplify.aws/react/build-a-backend/data/customize-authz/custom-data-access-patterns/"
---

You can define your own custom authorization rule with a Lambda function.

```ts title="amplify/data/resource.ts"
import {
  type ClientSchema,
  a,
  defineData,
  defineFunction,
} from '@aws-amplify/backend';

const schema = a.schema({
  Todo: a
    .model({
      content: a.string(),
    })
    // STEP 1
    // Indicate which models / fields should use a custom authorization rule
    .authorization(allow => [allow.custom()]),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'lambda',
    // STEP 2
    // Pass in the function to be used for a custom authorization rule
    lambdaAuthorizationMode: {
      function: defineFunction({
        entry: './custom-authorizer.ts',
      }),
      // (Optional) STEP 3
      // Configure the token's time to live
      timeToLiveInSeconds: 300,
    },
  },
});
```
<!-- Platform: javascript, angular, react-native, react, nextjs, vue, android, swift -->
In your application, you can perform CRUD operations against the model using `client.models.<model-name>` with the `lambda` auth mode.

```ts
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource'; // Path to your backend resource definition

const client = generateClient<Schema>();

const { errors, data: newTodo } = await client.models.Todo.create(
  {
    content: 'My new todo',
  },
  // highlight-start
  {
    authMode: 'lambda',
  }
  // highlight-end
);
```
<!-- /Platform -->

<!-- Platform: flutter -->
In your application, you can perform CRUD operations against the model with the `function` auth mode.

```dart
try {
  final todo = Todo(content: 'My new todo');
  final request = ModelMutations.create(
    todo,  
    authorizationMode: APIAuthorizationType.function,
  );
  final createdTodo = await Amplify.API.mutations(request: request).response;

  if (createdTodo == null) {
    safePrint('errors: ${response.errors}');
    return;
  }
  safePrint('Mutation result: ${createdTodo.name}');

} on APIException catch (e) {
  safePrint('Failed to create todo', e);
}
```
<!-- /Platform -->

The Lambda function of choice will receive an authorization token from the client and execute the desired authorization logic. The AppSync GraphQL API will receive a payload from Lambda after invocation to allow or deny the API call accordingly.

To configure a Lambda function as the authorization mode, create a new file `amplify/data/custom-authorizer.ts`. You can use this Lambda function code template as a starting point for your authorization handler code:

```ts
// amplify/data/custom-authorizer.ts

// This is sample code. Update this to suite your needs
import type { AppSyncAuthorizerHandler } from 'aws-lambda'; // types imported from @types/aws-lambda

type ResolverContext = {
  userid: string;
  info: string;
  more_info: string;
};

export const handler: AppSyncAuthorizerHandler<ResolverContext> = async (
  event
) => {
  console.log(`EVENT: ${JSON.stringify(event)}`);
  const {
    authorizationToken,
    requestContext: { apiId, accountId }
  } = event;
  const response = {
    isAuthorized: authorizationToken === 'custom-authorized',
    resolverContext: {
      // eslint-disable-next-line spellcheck/spell-checker
      userid: 'user-id',
      info: 'contextual information A',
      more_info: 'contextual information B'
    },
    deniedFields: [
      `arn:aws:appsync:${process.env.AWS_REGION}:${accountId}:apis/${apiId}/types/Event/fields/comments`,
      `Mutation.createEvent`
    ],
    ttlOverride: 300
  };
  console.log(`RESPONSE: ${JSON.stringify(response, null, 2)}`);
  return response;
};
```

You can use the template above as a starting point for your custom authorization rule. The authorization Lambda function receives the following event:

```json
{
    "authorizationToken": "ExampleAuthToken123123123", # Authorization token specified by client
    "requestContext": {
        "apiId": "aaaaaa123123123example123", # AppSync API ID
        "accountId": "111122223333", # AWS Account ID
        "requestId": "f4081827-1111-4444-5555-5cf4695f339f",
        "queryString": "mutation CreateEvent {...}\n\nquery MyQuery {...}\n", # GraphQL query
        "operationName": "MyQuery", # GraphQL operation name
        "variables": {} # any additional variables supplied to the operation
    }
}
```

Your Lambda authorization function needs to return the following JSON:

```json
{
  // required
  "isAuthorized": true, // if "false" then an UnauthorizedException is raised, access is denied
  "resolverContext": { "banana": "very yellow" }, // JSON object visible as $ctx.identity.resolverContext in VTL resolver templates

  // optional
  "deniedFields": ["TypeName.FieldName"], // Forces the fields to "null" when returned to the client
  "ttlOverride": 10 // The number of seconds that the response should be cached for. Overrides default specified in "amplify update api"
}
```

Review the Amplify documentation to set the custom authorization token for the [Data client](/[platform]/frontend/data/connect-to-API/).
