9

I am having a very hard time to figure out how to handle unauthenticated users in a React app which uses AWS Amplify and AWS AppSync. Seems like most docs suggest to wrap the whole app with withAuthenticator HOC from aws-amplify-react but in the real world it is a very rare case.

So here how I am setting a client to talk to the AppSync API

const client = new AWSAppSyncClient({
  url: AppSyncConfig.aws_appsync_graphqlEndpoint,
  region: AppSyncConfig.aws_appsync_region,
  auth: {
    type: AUTH_TYPE.AMAZON_COGNITO_USER_POOLS,
    jwtToken: async () =>
      (await Auth.currentSession()).getIdToken().getJwtToken()
  }
});

and then I wrap top level App component export default withAuthenticator(App);

All these works, a user hits the root URL and gets provided with a log in view. As it has been said above, it is a very rare case in the real world scenario. Usually, the root URL, as well as many others, is open to unauthenticated users. How to accomplish it with AWS Amplify? - no docs, not tuts :-(

I found some hint how to make it work here, yet still no complete explanation.

SaidAkh
  • 1,661
  • 4
  • 15
  • 28

3 Answers3

13
  1. Make sure to update your authentication settings to enable both authenticated and unauthenticated access by running amplify update auth and configuring the settings manually.

  2. In an API request, you can now specify the auth mode:

const createdTodo = await API.graphql({
  query: queries.createTodo,
  variables: {input: todoDetails},
  authMode: 'AWS_IAM'
});

Here are more detailed docs


These steps are outdated but also still work:

Using the following steps, you can allow both Authenticated & Unauthenticated access to your AWS AppSync API:

  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.
Nader Dabit
  • 52,483
  • 13
  • 107
  • 91
  • 1
    Thank you @Nader. This post helps me understand how @auth directive (probably) works underneath. You have minor typos `Mutation/fields/listTodos` should be `Query/..` in both examples. – ronaldwidha May 05 '19 at 03:58
  • 1
    does this mean that I can no longer use the `@auth` directives. As soon as I use the @auth directive, I get 403 forbidden for both unauth and auth. I'm guessing all the generated resolvers have to be updated since we switch `AWS_IAM` – ronaldwidha May 06 '19 at 02:49
  • 1
    IAM is currently not supported by @auth https://github.com/aws-amplify/amplify-cli/issues/1043 – ronaldwidha May 07 '19 at 00:48
  • 2
    Doesn't work as of Amplify 4.18.1. ```error: No Cognito Identity pool provided for unauthenticated access App.vue:35 [WARN] 10:21.110 AWSAppSyncRealTimeProvider - ensure credentials error No Cognito Identity pool provided for unauthenticated access 2 ConsoleLogger.js:107 [WARN] 10:21.111 AWSAppSyncRealTimeProvider - ensure credentials error No Cognito Identity pool provided for unauthenticated access ConsoleLogger.js:107 Error: No credentials 3 vendor.js line 347 > eval:842:35``` ​ – npskirk Apr 27 '20 at 18:12
  • Does it enable to mutate without authentication? – SalahAdDin Apr 27 '21 at 12:45
  • Dont forget that you need to override the provider for public access in the schema.json. The default provider for public access is API_KEY, which is probably not what you want when you enabled public access in IAM e.g.: `@auth(rules: [ { allow: owner }, { allow: public, provider: iam, operations: [read]}])` – Martin Franz Apr 20 '23 at 14:02
1

A little additional help to anyone suffering from Unauthorized (your problem is with AppSync) or 401 (your problem is with IAM/Unauth role setup).

We have COGNITO POOLS as our default authorizer. In order to use AWS_IAM, you'll need to go and add it in AppSync, then tweak the UNAUTH role of the identity pool (as described so well above). But there's a last gotcha --

Add @aws_iam directives on the query/mutation/model that are involved in the anonymous transaction, this should stop amplify returning the Unauthorized error, however you may well see more errors returned if you haven't allowed the objects' fields with the directive too.

Hope this helps. Check the documentation here for the correct directives for your setup.

https://aws.amazon.com/blogs/mobile/using-multiple-authorization-types-with-aws-appsync-graphql-apis/

MonsCamus
  • 131
  • 1
  • 4
0

I am guessing that the use case is give access to your graphql api to unauth and auth users, giving them different permissions (for example auth users can do mutations and unauth users just some queries). If that is the case you need to configure AWS IAM as an authentication type on your AppSync API, also you will need an Amazon Cognito IdentityPool that has unauth and auth access, and configure the IAM roles for those according to your requirements.

You can find a more detailed answer here

  • Thank you @FranciscoR. Can you please elaborate on this "configure the IAM roles for those according to your requirements"? Cannot figure out exactly what roles and how configure them. – SaidAkh Dec 20 '18 at 11:22
  • 1
    Im guessing @FranciscoR means restrict unauthenticated role access to certain GraphQL operations as described here https://docs.aws.amazon.com/appsync/latest/devguide/security.html#aws-iam-authorization – tgk Jan 01 '19 at 04:05