@auth on two 1-many connections
See original GitHub issue** Which Category is your question related to? **
AppSync
** What AWS Services are you utilizing? **
Cognito, AppSync @aws-amplify/cli v1.8.4 aws-amplify v1.1.32
** Provide additional details e.g. code snippets **
I have 2 tables with differing levels of auth on them, and I have a table which joins connections between the two.
The Brand model has dynamic group auth, which is assigned to a user in Cognito (e.g. “brand-1, brand-2, brand-3”) and then each row has one or more of those groups in the groups field. Users are also assigned to a generic “brand” group in Cognito, which means they can read everything from the Event model.
type Brand @model @auth (rules: [
{ allow: groups, groups: ["admin"], operations: [create, read, update, delete] },
{ allow: groups, groupsField: "groups", operations: [read, update] }
]) {
id: ID!
name: String!
groups: [String!]
eventBrands: [EventBrand!] @connection(name: "EventBrandBrand")
}
type Event @model @auth (rules: [
{ allow: groups, groups: ["admin"], operations: [create, read, update, delete] },
{ allow: groups, groups: ["brand"], operations: [read] }
]) {
id: ID!
name: String
brands: [EventBrand!] @connection(name: "EventBrandEvent")
}
type EventBrand @model {
id: ID!
event: Event! @connection(name: "EventBrandEvent")
brand: Brand! @connection(name: "EventBrandBrand")
}
For arguments sake I have entered two brands, and two events. I have then added an EventBrand for brand-1/event-1, and I have added a second EventBrand for brand-2/event-2.
When I query the EventBrand model, I get results back, which is great - but instead of ignoring items with connections I’m not authorised to retrieve, it simply returns a null item and generates an error for each of those connections.
This doesn’t really suit our use case, as our users could in theory be paging through empty page after empty page until they get theirs.
Response:
{
"data":{
"listEventBrands":{
"items":[
null, // <---- NULL ITEM HERE
{
"id":"2eb450cd-3b27-4657-89a4-f4cf709757b4",
"event":{
"id":"15cd1ab9-051c-4a2b-9709-ff81dcb63cb8",
"name":"Event 1",
},
"brand":{
"id":"1c66565b-af2f-4dc4-97a8-043be12b0de0",
"name":"Brand 1",
"groups":[
"brand-1"
]
}
}
],
"nextToken":null
}
},
"errors":[
{
"path":[
"listEventBrands",
"items",
0,
"brand"
],
"data":null,
"errorType":"Unauthorized",
"errorInfo":null,
"locations":[
{
"line":19,
"column":7,
"sourceName":null
}
],
"message":"Not Authorized to access brand on type EventBrand"
}
]
}
I then tried adding @auth directive to the EventBrand model, and targeting the brand.groups field. The response mapping template looks correct, but I get nothing returned.
Model:
type EventBrand @model @auth (rules: [
{ allow: groups, groups: ["admin"], operations: [create, read, update, delete] },
{ allow: groups, groupsField: "brand.groups", operations: [read] }
]) {
id: ID!
event: Event! @connection(name: "EventBrandEvent")
brand: Brand! @connection(name: "EventBrandBrand")
}
Response mapping template:
## [Start] If not static group authorized, filter items **
#if( ! $isStaticGroupAuthorized )
#set( $items = [] )
#foreach( $item in $ctx.result.items )
## [Start] Dynamic Group Authorization Checks **
#set( $userGroups = $util.defaultIfNull($ctx.identity.claims.get("cognito:groups"), []) )
#set( $isLocalDynamicGroupAuthorized = false )
## Authorization rule: { allow: groups, groupsField: "brand.groups" } **
#set( $allowedGroups = $item.brand.groups )
#foreach( $userGroup in $userGroups )
#if( $util.isList($allowedGroups) )
#if( $allowedGroups.contains($userGroup) )
#set( $isLocalDynamicGroupAuthorized = true )
#end
#end
#if( $util.isString($allowedGroups) )
#if( $allowedGroups == $userGroup )
#set( $isLocalDynamicGroupAuthorized = true )
#end
#end
#end
## [End] Dynamic Group Authorization Checks **
## No Owner Authorization Rules **
#if( ($isLocalDynamicGroupAuthorized == true || $isLocalOwnerAuthorized == true) )
$util.qr($items.add($item))
#end
#end
#set( $ctx.result.items = $items )
#end
## [End] If not static group authorized, filter items **
Result:
{"data":{"listEventBrands":{"items":[],"nextToken":null}}}
I have tried debug the Request Mapping template, but have had no success/can’t figure out how to do it.
I also tried querying the Event or Brand models and passing a filter where brand/event connection is null, but the brand is not part of the ModelEventFilterInput type.
export type ModelEventFilterInput = {
id?: ModelIDFilterInput | null,
name?: ModelStringFilterInput | null,
and?: Array< ModelEventFilterInput | null > | null,
or?: Array< ModelEventFilterInput | null > | null,
not?: ModelEventFilterInput | null,
};
export type ModelBrandFilterInput = {
id?: ModelIDFilterInput | null,
name?: ModelStringFilterInput | null,
groups?: ModelStringFilterInput | null,
and?: Array< ModelBrandFilterInput | null > | null,
or?: Array< ModelBrandFilterInput | null > | null,
not?: ModelBrandFilterInput | null,
};
So my questions are:
- Am I implementing the auth correctly?
- If I am, is there a way to ignore the null items from the response?
- Do I have an option 3?
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (1 by maintainers)
@nathan-quinn, about Example 2 - I understand the problem, but what should be the solution: I’d like to define the
groups
value on the main model (let say “Account”), and “child” models (e.g. “projects”) should inherit somehow the same group values of the parent.Do I have to add the same
groups
value on all models?I had this issue. It was because I had generated the schema with @model(queries: null) or something along those lines, which was not adding @aws-api-key to my models when amplify creates the actual build schema. I use api keys to make requests. Remove the (queries: null) part of the models to generate queries and then
amplify push
to update your backend.