Describe the bug
Our model contains Projects, that unauthenticated users of a mobile app should be able to read, and also to subscribe to updates to these objects. Hence our graphql schema contains:
type Project
@model(subscriptions: { level: public })
@auth(
rules: [
{
allow: private
provider: userPools
operations: [read, create, update, delete]
}
{ allow: public, provider: iam, operations: [read] }
]
) {
But when the client tries to subscribe to updates (verifiable also in the AppSync console), an error for unauthorised access is thrown, despite only read access is required, and also subscriptions for the model is set to public. There should be a way for unauthenticated clients to subscribe to public models.
"errors": [
{
"path": [
"onUpdateProject"
],
"data": null,
"errorType": "Unauthorized",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Not Authorized to access onUpdateProject on type Subscription"
}
The only way to have the proper resource statements generated in the cloudformation scripts for the unauthRole is to include update
in the list of operations.
Amplify CLI Version
3.15.0
To Reproduce
see above
Expected behavior
if read access is allowed for public, it should be possible to subscribe to updates
What is the default Authorization mode for your API? Could you try subscribing to API using the default authorization mode and see if the subscription succeeds
This the backend-config.json
"api": {
"fooBarApi": {
"service": "AppSync",
"providerPlugin": "awscloudformation",
"output": {
"authConfig": {
"additionalAuthenticationProviders": [
{
"authenticationType": "AWS_IAM"
}
],
"defaultAuthentication": {
"authenticationType": "AMAZON_COGNITO_USER_POOLS",
"userPoolConfig": {
"userPoolId": "xxx"
}
}
}
}
},
AFAIK there's no unauth access with userpools, is there? so I don't know how to subscribe to the api with the default auth mode.
as far as I can tell, the transformer doesn't generate the required resources in the unauth role to grant access to the subscriptions.
When multi auth is enabled, the subscriptions support only the default auth type even if its declared as public
. The transformer is not generating the required multi auth directives to support all the auth types enabled in your API. I am marking this as bug.
the workaround for this issue is to extend subscription in your schema and adding the auth directives manually as shown below
type Subscription {
onCreateProjectPublic: Project
@aws_subscribe(mutations: ["createProject"])
@aws_iam
@aws_cognito_user_pools
onUpdateProjectPublic: Project
@aws_subscribe(mutations: ["updateProject"])
@aws_iam
@aws_cognito_user_pools
onDeleteProjectPublic: Project
@aws_subscribe(mutations: ["deleteProject"])
@aws_iam
@aws_cognito_user_pools
}
The workaround suggested by @yuth worked for me but only after I also added the permission to the UnauthRole policy:
arn:aws:appsync:us-east-1:[...]:apis/[...]/types/Subscription/fields/onUpdateProjectPublic
I made this change directly in the IAM console as I couldn't find a way to do it by editing the Amplify files
Hi @AndreasEK
PR: https://github.com/aws-amplify/amplify-cli/pull/4340 address this by adding read on the permissions the GraphQL Transformer will add the necessary permissions to allow the unauthRole
to listen to subscriptions.
The workaround suggested by @yuth worked for me but only after I also added the permission to the UnauthRole policy:
arn:aws:appsync:us-east-1:[...]:apis/[...]/types/Subscription/fields/onUpdateProjectPublic
I made this change directly in the IAM console as I couldn't find a way to do it by editing the Amplify files
@andriworld You can do it in CustomResources.json
file:
...
"Resources": {
"UnauthRolePolicy": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "appsync-unauthrole-policy-custom",
"Roles": [
{
"Ref": "unauthRoleName"
}
],
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["appsync:GraphQL"],
"Resource": [
{
"Fn::Sub": [
"arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/${apiId}/types/${typeName}/fields/${fieldName}",
{
"apiId": {
"Ref": "AppSyncApiId"
},
"typeName": "Subscription",
"fieldName": "onUpdateProjectPublic"
}
]
}
]
}
]
}
}
}
},
...
Closing this issue as the PR for this has been merged and and released into version 4.21.1. By adding the read operation this will generate the IAM policies to allow access to subscriptions.
Hi @SwaySway, the fix didn't work for my model (amplify CLI version 4.21.3)
type Project @model(subscriptions: { level: public })
@auth(
rules: [
{ allow: public, provider: iam, operations: [read] }
{ allow: owner, operations: [create, read, update ] }
]
) {
No subscription permissions are added to the IAM policies (and the multiple auth directives are missing from the schema)
I also tested changing the model to this:
type Project @model
@auth(
rules: [
{ allow: public, provider: iam, operations: [read] }
{ allow: owner, operations: [create, read, update ] }
]
) {
The permissions are added, but now only the owner of a project can subscribe to its updates.
Is there something else I should do?
Thank you
@andriworld Were you able to resovle?
I'm facing the same issue on version 4.26.0
This is my model
type Book
@model
@auth(
rules: [
{ allow: groups, groups: ["Admins"] }
{ allow: groups, groupsField: "level1", operations: [update, read] }
{ allow: groups, groupsField: "level2", operations: [read] }
]
In this case admins can subscribe. but level1 can't.
I am still seeing this same behavior on version 4.29.2 with this model:
type Account @model
@auth(rules: [
{
allow: owner, ownerField: "id", identityField: "custom:accountNumber",
operations: [read]
}
{ allow: groups, groups: ["admin"] }
])
{
id: ID!
name: String
description: String
}
owner can read, but on trying to subscribe to update, get unauthorized error.
@SwaySway Is this expected behavior after the PR merge or have I hit a new case?
Seems like read permission should allow for subscribing to updates.
I'm on 4.29.4.. And am also seeing the same behaviour. I guess I should create a new Issue though
@SwaySway I'm on 4.29.5
type Post
@model(subscriptions: { level: public })
@aws_iam
@aws_cognito_user_pools
@auth(
rules: [
{ allow: owner, operations: [create, read, update, delete] }
{ allow: public, provider: iam, operations: [read, update] }
{ allow: groups, groups: ["user"], operations: [create, read, update] }
]
)
@key(name: "byUser", fields: ["userID"]) {
id: ID!
title: String!
userID: ID!
content: String
user: User @connection(fields: ["userID"])
comments: [Comment] @connection(keyName: "byPost", fields: ["id"])
}
Owner can read, but when it is aws_iam, "no current user"
Most helpful comment
When multi auth is enabled, the subscriptions support only the default auth type even if its declared as
public
. The transformer is not generating the required multi auth directives to support all the auth types enabled in your API. I am marking this as bug.the workaround for this issue is to extend subscription in your schema and adding the auth directives manually as shown below