Can't set field-level authorization in amplify gen2
Environment information
System:
OS: Windows 10 10.0.19045
CPU: (8) x64 Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
Memory: 1.06 GB / 7.86 GB
Binaries:
Node: 20.16.0 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
npm: 10.8.1 - C:\Program Files\nodejs\npm.CMD
pnpm: undefined - undefined
NPM Packages:
@aws-amplify/backend: 1.0.4
@aws-amplify/backend-cli: 1.1.1
aws-amplify: 6.5.0
aws-cdk: 2.149.0
aws-cdk-lib: 2.149.0
typescript: 5.5.3
AWS environment variables:
AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
AWS_SDK_LOAD_CONFIG = 1
AWS_STS_REGIONAL_ENDPOINTS = regional
No CDK environment variables
Description
Even after specifying field level authorization for all required fields, it says required fields missing field-level authorization rules: below is the schema file amplify/data/resource.ts
import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
const schema = a.schema({
Comment: a.customType({
content: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
username: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
dp: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
dn: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
}),
Video: a
.model({
partitionKey: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
]),
sortKey: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
]), ////video title or username + uuidv1
type: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
]), ///specify type to avoid confusion
category: a.string(), /// category which is partition key for video entry
debate: a.json().array(), ///debate of the video
description: a.string(), ///channel or video description
url: a.string(), ///video url
thumbnail: a.string(), ///video thumbnail
dp: a.string(), ///user dp can store in both cases,
comment: a
.ref("Comment")
.array()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]), ///only in case of video
dn: a.string(), //display name
username: a.string(),
})
.identifier(["partitionKey", "sortKey"])
.authorization((allow) => [
// allow.publicApiKey(),
allow.publicApiKey().to(["read"]),
// Allow signed-in user to create, read, update,
// and delete their __OWN__ posts.
allow.owner(),
]),
});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: "apiKey",
// API Key is used for a.allow.public() rules
apiKeyAuthorizationMode: {
expiresInDays: 30,
},
},
});
The error from the terminal is as below:
Failed to instantiate data construct
Caused By: When using field-level authorization rules you need to add rules to all of the model's required fields with at least read permissions. Found model "Video" with required fields ["partitionKey","sortKey","type"] missing field-level authorization rules.\n\nFor more information visit https://docs.amplify.aws/ction-rules
Hey,👋 thanks for raising this! I'm going to transfer this over to our API repository for better assistance 🙂
Hey @binarycombinatrix, When using field-level authorization, you must grant at least read permissions to the remaining fields. I've noticed that the category, debate, description, url, thumbnail, dp, dn, and username fields in the Video model are missing permissions. Please modify the fields as shown below and let me know if this resolves your issue.
Video: a
.model({
partitionKey: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
]),
sortKey: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
]), ////video title or username + uuidv1
type: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
]), ///specify type to avoid confusion
category: a
.string()
.authorization((allow) => [allow.publicApiKey().to(["read"])]),
debate: a
.json()
.array()
.authorization((allow) => [allow.publicApiKey().to(["read"])]), ///debate of the video
description: a
.string()
.authorization((allow) => [allow.publicApiKey().to(["read"])]), ///channel or video description
url: a
.string()
.authorization((allow) => [allow.publicApiKey().to(["read"])]), ///video url
thumbnail: a
.string()
.authorization((allow) => [allow.publicApiKey().to(["read"])]), ///video thumbnail
dp: a
.string()
.authorization((allow) => [allow.publicApiKey().to(["read"])]), ///user dp can store in both cases,
comment: a
.ref("Comment")
.array()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]), ///only in case of video
dn: a
.string()
.authorization((allow) => [allow.publicApiKey().to(["read"])]), //display name
username: a
.string()
.authorization((allow) => [allow.publicApiKey().to(["read"])]),
})
.identifier(["partitionKey", "sortKey"])
.authorization((allow) => [
// allow.publicApiKey(),
allow.publicApiKey().to(["read"]),
// Allow signed-in user to create, read, update,
// and delete their __OWN__ posts.
allow.owner(),
]),
Hi @AnilMaktala did you try running your version? Those other fields are not required fields and so do not require field level auth, as the model level authorization applies to them and I added publicApi read to it already.
The error too says the issue is with required fields.
I believe there is a bug with the error message. The error message is present when including allow.authenticated() on the comment field.
comment: a
.ref("Comment")
.authorization((allow) => [
allow.authenticated(),
]),
I'm not sure why this is causing this error, but you may want to change this anyway. This auth configuration allows any user to modify the comments associated with a video (even videos they do not own). That means any authenticated user could remove comments from a video.
I assume you set this auth so that any user could leave a comment on a given video. A more secure way to implement this would be to create a custom mutation (such as createCommentOnVideo). This would allow authenticated users to add comments to a video, but not remove them.
https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/
Hey @binarycombinatrix, After further investigation, we found that the comment model has publicApiKey and authenticated auth settings. To resolve the issue, you need to grant access to authenticated users for the required fields as well. Below is the updated schema. Please try it out and let me know the results.
import {
type ClientSchema,
a,
defineData,
defineFunction,
} from "@aws-amplify/backend";
//const echoHandler = defineFunction({ entry: "./echo-handler/handler.ts" });
const schema = a.schema({
Comment: a.customType({
content: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
username: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
dp: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
dn: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]),
}),
Video: a
.model({
partitionKey: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
allow.authenticated(),
]),
sortKey: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
allow.authenticated(),
]), ////video title or username + uuidv1
type: a
.string()
.required()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.owner(),
allow.authenticated(),
]), ///specify type to avoid confusion
category: a.string(), /// category which is partition key for video entry
debate: a.json().array(), ///debate of the video
description: a.string(), ///channel or video description
url: a.string(), ///video url
thumbnail: a.string(), ///video thumbnail
dp: a.string(), ///user dp can store in both cases,
comment: a
.ref("Comment")
.array()
.authorization((allow) => [
allow.publicApiKey().to(["read"]),
allow.authenticated(),
]), ///only in case of video
dn: a.string(), //display name
username: a.string(),
})
.identifier(["partitionKey", "sortKey"])
.authorization((allow) => [
// allow.publicApiKey(),
allow.publicApiKey().to(["read"]),
// Allow signed-in user to create, read, update,
// and delete their __OWN__ posts.
allow.owner(),
]),
});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: "apiKey",
// API Key is used for a.allow.public() rules
apiKeyAuthorizationMode: {
expiresInDays: 30,
},
},
});
Hey 👋 , This issue is being closed due to inactivity. If you are still experiencing the same problem and need further assistance, please feel free to leave a comment. This will enable us to reopen the issue and provide you with the necessary support.
This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.