Amplify-js: GraphQL, AppSync and Auth.

Created on 1 Feb 2019  路  18Comments  路  Source: aws-amplify/amplify-js

GraphQL, AppSync, and Authentication.

I have an app which should allow people to obtain data from AppSync to display, i.e. in a Blog style app.

But AppSync/GraphQL won't allow me to obtain any data until I am authenticated. I need to be able to read data, while authenticated or unauthenticated.

To create my project, I ran through the amplify-js instructions to create and init a project.

My project uses Auth, Hosting, API, and Storage.

AppSync Auth Storage help wanted

Most helpful comment

@dabit3 The latest version of the amplify-cli goes through some extra steps and configures auth and unauth roles through cognito for me that I used to manually create using the instructions you gave me here... it only half works for me though now, it requires someone to be logged in, the unauth role does not apply. Is there something additional I need to do, or a step that I missed out. I made sure that Cognito allowed unauth logins, and I can see that the auth and unauth roles are created to allow AppSync requests to the data neccessary, but it just won't load up any data unless I sign in.

All 18 comments

@michaelcuneo I created a similar project last year, I will be adding the instructions on how to accomplish this on this issue.

I had no problem creating something like this last year, when I had the more modular, less HoC, version of aws-amplify-cli ... but now that I'm using amplify-js and have a lot less configurable parts exposed, finding out how to change things to make simple things like allowing read graphQL unauthed, isn't immediately noticeable. Because the entire GraphQL generation process was all automated there wasn't anywhere that I could throw a 'read public' or something, to make it work. ... Not that I could see anyway, maybe I missed something while reading.

I found Nader's articles on Medium (e.g. React, React Native) very helpful. He links to sample repos for apps with unauth'd and auth'd pages.

@michaelcuneo we're working on automating this easily in a newer version of the CLI.

In the meantime, use the following steps:

  1. Create an Amplify project
amplify init
  1. Add auth with custom security configuration:
amplify add auth

Do you want to use the default authentication and security configuration? __NO__

Select the authentication/authorization services that you want to use: (Use arrow keys)
__User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and more)__

Please provide a friendly name for your resource that will be used to label this category in the project: __YOURAPINAME__

Please enter a name for your identity pool. __YOURIDPOOLNAME__

Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) __Yes__

__Choose defaults for the rest of the questions__

  1. Add the api
amplify add api

Choose __Amazon Cognito User Pool__ as the authorization type.

  1. Create the API
amplify push
  1. In the AppSync API dashboard settings, change the authentication type to __AWS Identity and Access Management (IAM)__

  2. In aws.exports.js on the client app, change aws_appsync_authenticationType to AWS_IAM

  3. In the Cognito dashboard, click "Manage Identity Pools" & click on your identity pool.

  4. Click "Edit Identity Pool" to see your "Unauthenticated role" & "Authenticated Role"

  5. Open the IAM console & find the "Unauthenticated role" from step 8

  6. Click "Add inline policy"

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:<REGION>:<ACCOUNTID>:apis/<APIID>/types/Mutation/fields/listTodos"
            ]
        }
    ]
}
  1. Open the IAM console & find the "Authenticated role" from step 8

  2. Click "Add inline policy"

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:<REGION>:<ACCOUNTID>:apis/<APIID>/types/Mutation/fields/listTodos",
                "arn:aws:appsync:<REGION>:<ACCOUNTID>:apis/<APIID>/types/Mutation/fields/createTodo"
            ]
        }
    ]
}
  1. In index.js, add this code:
import { Auth } from 'aws-amplify'
Auth.currentCredentials()
  .then(d => console.log('data: ', d))
  .catch(e => console.log('error: ', e))
  1. You should now be able to query when logged out, & query & create mutations when logged in.

If you'd like to access the unique identity of the logged in user for user authorization & fine grained access control, you can access the $context.identity.cognitoIdentityId) in the resolver.

I'll try reinit from scratch. I just did a hack to change my existing project to all of this, but every time I change the aws_appsync_authenticationType to AWS_IAM, every time I hit amplify push, it modifies it back to AMAZON_COGNITO_USER_POOLS ... I guess it needs to be done from scratch. I'll just store my old GraphQL and S3 Config somewhere so I can reproduce it...

I've managed to get AWS_IAM to stay put... by editing all of the files, not just autogenerated aws-exports.js ... should step 6 be done before step 4. Oh wait, it can't be done before Step 4, because it doesn't exist in Step 4... 馃憤

So I had to edit the SecurityType under API, in amplify-meta.json in backend, then it would persist my change from AWS_COGNITO_USER_POOLS to AWS_IAM.

It now says AWS_IAM, but didn't change anything after a push. Both operations said 'NO CHANGE'

After all of the changes, I still get the following result from an unauth GraphQL request.

{
  "errors" : [ {
    "errorType" : "UnauthorizedException",
    "message" : "Unable to parse JWT token."
  } ]
}

I realised my schema doesn't have listTodos or createTodo's... and I performed step 5 in the wrong AppSync project, so I fixed both of these issues... then continued.

I changed the Resource in the policies to my actual resources.. Query/listPosts, and Mutation/createPost

Unauth Role for listing Posts.
"Resource": "arn:aws:appsync[region]:[AccountID]:apis/[Api ID]/types/Query/fields/listPosts"
Auth Role for both.

"Resource": [
                "arn:aws:appsync:[region]:[account ID]:apis/[Api ID]/types/Query/fields/listPosts",
                "arn:aws:appsync:[region]:[account ID]:apis/[Api ID]/types/Mutation/fields/createPost"
]

Since this change... everything appears to be 100% 馃憤

Is this ok to close now? @michaelcuneo

@jordanranz Yeah, thanks. Makes way more sense now. :)

So When I am in my appsync queries console i get "message": "Not Authorized to access createCoin on type Coin"

Maybe you didn鈥檛 add the right arn to perform that createCoin function. Or it hasn鈥檛 been switched to IAM and still thinks it鈥檚 using Cognito?

Maybe its because I added an auth directive @auth( rules: [ { allow: groups groups: ["Members"] queries: [get, list] mutations: null } { allow: groups groups: ["Admin"] queries: null mutations: [create, update, delete] } ] ) where is the IAM role defined for your own aws account?

@amlcodes @auth directive only works for Cognito User Pools
https://aws-amplify.github.io/docs/cli/graphql
Take a look at the Task App

For the "unauthRole", I had to configure IAM roles like this:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "appsync:GraphQL",
            "Resource": "*"
        }
    ]
}

In the IAM console, the policy for "Unauthenticated role" has Resources set to all resources.

I can now query for data from my api without authentication BUT is this the right way? It works now but I'm curious to know if this will cause any problems in the future.

@michaelcuneo we're working on automating this easily in a newer version of the CLI.

In the meantime, use the following steps:

  1. Create an Amplify project
amplify init
  1. Add auth with custom security configuration:
amplify add auth

Do you want to use the default authentication and security configuration? NO

Select the authentication/authorization services that you want to use: (Use arrow keys)
User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and more)

Please provide a friendly name for your resource that will be used to label this category in the project: YOURAPINAME

Please enter a name for your identity pool. YOURIDPOOLNAME

Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) Yes

Choose defaults for the rest of the questions

  1. Add the api
amplify add api

Choose Amazon Cognito User Pool as the authorization type.

  1. Create the API
amplify push
  1. In the AppSync API dashboard settings, change the authentication type to AWS Identity and Access Management (IAM)
  2. In aws.exports.js on the client app, change aws_appsync_authenticationType to AWS_IAM
  3. In the Cognito dashboard, click "Manage Identity Pools" & click on your identity pool.
  4. Click "Edit Identity Pool" to see your "Unauthenticated role" & "Authenticated Role"
  5. Open the IAM console & find the "Unauthenticated role" from step 8
  6. Click "Add inline policy"
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:<REGION>:<ACCOUNTID>:apis/<APIID>/types/Mutation/fields/listTodos"
            ]
        }
    ]
}
  1. Open the IAM console & find the "Authenticated role" from step 8
  2. Click "Add inline policy"
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:<REGION>:<ACCOUNTID>:apis/<APIID>/types/Mutation/fields/listTodos",
                "arn:aws:appsync:<REGION>:<ACCOUNTID>:apis/<APIID>/types/Mutation/fields/createTodo"
            ]
        }
    ]
}
  1. In index.js, add this code:
import { Auth } from 'aws-amplify'
Auth.currentCredentials()
  .then(d => console.log('data: ', d))
  .catch(e => console.log('error: ', e))
  1. You should now be able to query when logged out, & query & create mutations when logged in.

If you'd like to access the unique identity of the logged in user for user authorization & fine grained access control, you can access the $context.identity.cognitoIdentityId) in the resolver.

Hey @michaelcuneo, sounds nice but I have a lot of data in my tables and users in my user pools, can I try this or do I have to run extra-steps?

Hey @michaelcuneo, sounds nice but I have a lot of data in my tables and users in my user pools, can I try this or do I have to run extra-steps?

Seems to work for me and everyone else, the amount of data and users wouldn't affect the AWS_IAM authorisation.

@dabit3 The latest version of the amplify-cli goes through some extra steps and configures auth and unauth roles through cognito for me that I used to manually create using the instructions you gave me here... it only half works for me though now, it requires someone to be logged in, the unauth role does not apply. Is there something additional I need to do, or a step that I missed out. I made sure that Cognito allowed unauth logins, and I can see that the auth and unauth roles are created to allow AppSync requests to the data neccessary, but it just won't load up any data unless I sign in.

Was this page helpful?
0 / 5 - 0 ratings