Reputation: 417
I recently got into AWS and I'm using appsync alongside a dynamo table with an idex for user id(from the cognito pool) to give only certain user access to certain data. Now I would like to further expand upon this and also give access to certain cognito groups. Here is my code:
1st. my mutation
## [Start] Prepare DynamoDB PutItem Request. **
$util.qr($context.args.input.put("createdAt", $util.time.nowISO8601()))
$util.qr($context.args.input.put("updatedAt", $util.time.nowISO8601()))
$util.qr($context.args.input.put("__typename", "Patient"))
## This line adds the userId, accessed from the $ctx.identity variable
$util.qr($context.args.input.put("userId", $ctx.identity.sub))
$util.qr($context.args.input.put("Groupi", $ctx.identity.claims.get("cognito:groups")))
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.args.input.id, $util.autoId()))
},
"attributeValues": $util.dynamodb.toMapValuesJson($context.args.input),
"condition": {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id"
}
}
}
and the query
#set( $limit = $util.defaultIfNull($context.args.limit, 10) )
{
"version" : "2017-02-28",
"operation" : "Query",
"limit": $limit,
"index": "userId-index",
"query" : {
"expression": "userId = :userId",
"expressionValues" : {
":userId" : $util.dynamodb.toDynamoDBJson($ctx.identity.sub)
}
},
"nextToken": #if( $context.args.nextToken )
"$context.args.nextToken"
#else
null
#end
}
I would like to expand the query to support t6he group aswell. Help would be much appreciated. Thanks!
Upvotes: 3
Views: 2714
Reputation: 2388
The other examples here seem more attuned to the 'fine grained access control' section, which depending on your needs may be the correct choice:
For more general cases, if you have a look at the 'Security' docs page, there is a good example for how to use directives directly in your GraphQL schema as well:
In particular for your use case, the @aws_auth
or @aws_cognito_user_pools
directives seem relevant. The full list is:
@aws_api_key
- To specify the field is API_KEY
authorized.@aws_iam
- To specify that the field is AWS_IAM
authorized.@aws_oidc
- To specify that the field is OPENID_CONNECT
authorized.@aws_cognito_user_pools
- To specify that the field is AMAZON_COGNITO_USER_POOLS
authorized.To copy the example from the docs page:
type Query {
posts:[Post!]!
@aws_auth(cognito_groups: ["Bloggers", "Readers"])
}
type Mutation {
addPost(id:ID!, title:String!):Post!
@aws_auth(cognito_groups: ["Bloggers"])
}
Upvotes: 0
Reputation: 5775
The authorization docs have lots of examples you might find helpful: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html
Specifically, this one:
#set($expression = "")
#set($expressionValues = {})
#foreach($group in $context.identity.claims.get("cognito:groups"))
#set( $expression = "${expression} contains(groupsCanAccess, :var$foreach.count )" )
#set( $val = {})
#set( $test = $val.put("S", $group))
#set( $values = $expressionValues.put(":var$foreach.count", $val))
#if ( $foreach.hasNext )
#set( $expression = "${expression} OR" )
#end
#end
{
"version" : "2017-02-28",
"operation" : "Scan",
"limit": #if(${context.arguments.count}) "${context.arguments.count}" #else 20 #end,
"nextToken": #if(${context.arguments.nextToken}) "${context.arguments.nextToken}" #else null #end,
"filter":{
"expression": "$expression",
"expressionValues": $utils.toJson($expressionValues)
}
}
That example has some extra info since it's about a list call rather than a simple get, however you can see it being set in the expression/expression values. This implementation looks a tad different than what you have as it allows a user to be in multiple groups, any one of which could work.
Does that make sense?
Upvotes: 2