Custom resolver / response VTL templates for fine grained auth with AppSync and DataStore

104 Views Asked by At

I have requirement for a non standard authentication model using amplify app sync. There are different levels of access that each user can have

  • public
  • private
  • sensitive

and for each of these there can be readonly or writeable access. Each object in the model can then be assigned to one of these levels of access. I have modeled this by having cognito user groups for each of these as

  • public
  • publicReadonly
  • private
  • privateReadonly
  • etc

that can be added to each user. Each object has a field groupAccess that then lists the groups that can access it. Non authenticated users can only access public objects with readonly access using API_KEY auth and authenticated users can query based on cognito user group. The model is defined as such

type Model @model @auth(rules: [{ allow: public, operations: [read] }, { allow: private }]) {
    id: ID!
    groupAccess: [String!]
}

I support this with multi auth and a custom response that checks the objects group against the users which works for querying

#if($ctx.error)
    $util.error($ctx.error.message, $ctx.error.type)
#end
#set($myResults = { "items": [] })
#set($claimPermissions = $context.identity.claims.get("cognito:groups"))
#foreach($item in $ctx.result.items)
    #set($isPublic = false)
    #set($hasPermissions = false)
    #set($isOwner = false)

    #foreach( $g in $item.groupAccess )
        #if($g == 'public')
            #set($isPublic = true)
        #end
        #foreach( $userGroup in $claimPermissions )
            #if($userGroup == $g)
                #set($hasPermissions = true)
            #end
        #end
    #end
    #if($ctx.identity)
        #if($item.owner == $ctx.identity.sub)
            #set($isOwner = true)
        #end
    #end
    #if($isOwner || $isPublic || $hasPermissions)
        #set($added = $myResults.items.add($item))
    #end
#end
$utils.toJson($myResults)

Now I need to make sure that records can only be updated / created by users with the correct groups and I am a little unsure of the best way to do this. Looking at https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html shows some use cases but it isn't clear to me which template I should be overriding in the generated resolvers and what the code should look like. A user should only be able to update a record based on the existing groupAccess field in dynamo and then this checked against the users groups.

Can someone point me in the right direction?

thanks

0

There are 0 best solutions below