amplify-android icon indicating copy to clipboard operation
amplify-android copied to clipboard

NullPointerException on isReadRestrictingStaticGroup when using dynamic group authorization

Open ObeA opened this issue 3 years ago • 5 comments

Before opening, please confirm:

Language and Async Model

Kotlin

Amplify Categories

DataStore

Gradle script dependencies

I'm not really sure. Dependencies are transient via amplify-flutter.

pubspec.yaml

amplify_flutter: ^0.2.8
amplify_api: ^0.2.8
amplify_datastore: ^0.2.8

Environment information

Welcome to Gradle 6.7!

Here are the highlights of this release:
 - File system watching is ready for production use
 - Declare the version of Java your build requires
 - Java 15 support

For more details see https://docs.gradle.org/6.7/release-notes.html


------------------------------------------------------------
Gradle 6.7
------------------------------------------------------------

Build time:   2020-10-14 16:13:12 UTC
Revision:     312ba9e0f4f8a02d01854d1ed743b79ed996dfd3

Kotlin:       1.3.72
Groovy:       2.5.12
Ant:          Apache Ant(TM) version 1.10.8 compiled on May 10 2020
JVM:          1.8.0_302 (Oracle Corporation 25.302-b08)
OS:           Linux 5.13.19-2-MANJARO amd64

Please include any relevant guides or documentation you're referencing

https://docs.amplify.aws/cli/graphql-transformer/auth/#dynamic-group-authorization

Describe the bug

I'm trying to use Datastore via Amplify Flutter on a schema with a dynamic group authorization rule. After configuration the app immediately throws a NullPointerException on isReadRestrictingStaticGroup. I'm opening the issue in this repo because it seems to be coming from this codebase.

W/amplify:aws-datastore(14059): An error occurred on the remote ON_UPDATE subscription for model Todo
W/amplify:aws-datastore(14059): java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.List.isEmpty()' on a null object reference
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.auth.AuthRuleRequestDecorator.isReadRestrictingStaticGroup(AuthRuleRequestDecorator.java:147)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.auth.AuthRuleRequestDecorator.decorate(AuthRuleRequestDecorator.java:103)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.AWSApiPlugin.buildSubscriptionOperation(AWSApiPlugin.java:628)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.AWSApiPlugin.subscribe(AWSApiPlugin.java:308)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.AWSApiPlugin.subscribe(AWSApiPlugin.java:288)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.ApiCategory.subscribe(ApiCategory.java:91)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.datastore.appsync.AppSyncClient.subscription(AppSyncClient.java:332)

Reproduction steps (if applicable)

No response

Code Snippet

Repo with minimal repro (Flutter required)

Log output

I/amplify:flutter:api(14059): Added API plugin
I/amplify:aws-datastore(14059): Creating table: PersistentModelVersion
I/amplify:aws-datastore(14059): Creating table: LastSyncMetadata
I/amplify:aws-datastore(14059): Creating table: Todo
I/amplify:aws-datastore(14059): Creating table: PersistentRecord
I/amplify:aws-datastore(14059): Creating table: ModelMetadata
I/amplify:aws-datastore(14059): Creating index for table: PersistentRecord
I/amplify:flutter:datastore(14059): Unhandled DataStoreHubEvent: SUCCEEDED
I/amplify:flutter:datastore(14059): com.amplifyframework.core.category.CategoryInitializationResult@69374e1
I/amplify:aws-datastore(14059): Orchestrator lock acquired.
I/amplify:aws-datastore(14059): Orchestrator transitioning from STOPPED to SYNC_VIA_API
I/amplify:aws-datastore(14059): Starting to observe local storage changes.
I/amplify:aws-datastore(14059): Now observing local storage. Local changes will be enqueued to mutation outbox.
I/amplify:aws-datastore(14059): Setting currentState to LOCAL_ONLY
I/amplify:aws-datastore(14059): Setting currentState to SYNC_VIA_API
I/amplify:aws-datastore(14059): Starting API synchronization mode.
I/amplify:flutter:datastore(14059): Established a new stream form flutter com.amplifyframework.datastore.storage.sqlite.-$$Lambda$coxN3FV0myAqN-gpZfZvj7bzSOI@bb578af
I/amplify:aws-datastore(14059): Orchestrator lock released.
I/amplify:aws-datastore(14059): Starting processing subscription events.
W/amplify:aws-datastore(14059): An error occurred on the remote ON_UPDATE subscription for model Todo
W/amplify:aws-datastore(14059): java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.List.isEmpty()' on a null object reference
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.auth.AuthRuleRequestDecorator.isReadRestrictingStaticGroup(AuthRuleRequestDecorator.java:147)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.auth.AuthRuleRequestDecorator.decorate(AuthRuleRequestDecorator.java:103)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.AWSApiPlugin.buildSubscriptionOperation(AWSApiPlugin.java:628)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.AWSApiPlugin.subscribe(AWSApiPlugin.java:308)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.aws.AWSApiPlugin.subscribe(AWSApiPlugin.java:288)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.api.ApiCategory.subscribe(ApiCategory.java:91)
W/amplify:aws-datastore(14059): 	at com.amplifyframework.datastore.appsync.AppSyncClient.subscription(AppSyncClient.java:332)

amplifyconfiguration.json

{
    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "api": {
        "plugins": {
            "awsAPIPlugin": {
                "amplifyoidcissue": {
                    "endpointType": "GraphQL",
                    "endpoint": "https://xxxxxx.appsync-api.eu-west-1.amazonaws.com/graphql",
                    "region": "eu-west-1",
                    "authorizationType": "OPENID_CONNECT"
                }
            }
        }
    }
}

GraphQL Schema

type Todo @model @auth(rules: [
  	{ allow: owner, ownerField: "owner", provider: oidc, identityClaim: "sub" },
    { allow: groups, provider: oidc, groupsField: "groupsCanEdit", groupClaim: "groups", groups: [] },
    { allow: groups, provider: oidc, groupsField: "groupsCanAccess", groupClaim: "groups", operations: [read], groups: [] }
  ]) {
  id: ID!
  name: String!
  description: String

  groupsCanAccess: [String]!
  groupsCanEdit: [String]!
  owner: String
}

Additional information and screenshots

No response

ObeA avatar Nov 16 '21 15:11 ObeA

I imagine it has something to do with a known limitation that is mentioned in the new documentation:

Known limitation: Real-time subscriptions are not supported for dynamic group authorization.

Nonetheless, pretty disappointing.

jwshyns avatar Jan 19 '22 03:01 jwshyns

Hi @ObeA, what jwshyns has said above is correct, and agreed that this is a pretty disappointing user experience. In the immediate future this is not supported, but we are looking at ways to unblock use cases like this this year.

alharris-at avatar Apr 20 '22 18:04 alharris-at

With this finally released for AppSync, https://aws.amazon.com/blogs/mobile/appsync-enhanced-filtering/ and with the CLI adding support soon: aws-amplify/amplify-category-api#389 what is the timeline for dynamic group support for subscriptions for android? Would making SyncExpressions server sided also make sense?

djorgji avatar May 09 '22 20:05 djorgji

@djorgji Our plan for the functionality mentioned in that comment includes providing some mechanism to pass server-side sync metadata up from the client, but the DX for that and associated API changes haven't been designed yet from a DataStore perspective. We are, however, tracking that as part of our support model across Amplify for enhanced server-side filtering.

I believe this should remove the primary technical blocker to dynamic group subscription filtering, but will tag this to the project so we evaluate this use-case as part of the design process.

alharris-at avatar May 09 '22 23:05 alharris-at

@alharris-at Thank you for the reply! I am excited for the update, it is validating our choice to pick AWS Amplify and stick out through the limitations. Ideally from a security, scalability and optimization perspective running dynamic group filtering, and running sync expressions (or a similar mechanism) in the backend, would be amazing. Please keep us updated.

djorgji avatar May 10 '22 13:05 djorgji