Enabling unauthenticated access with AWS Amplify

Temps de lecture : 7 minutes

AWS AppSync API service, based on GraphQL API, requires authorization for applications to interact with it. The preferred method of authorization relies on IAM with tokens provided by Cognito User Pools or other OpenID Connect providers. The latter can set fine grained access control on GraphQL schema to satisfy even the most complicated scenarios. Public APIs do not require authorization and those can be built using API keys.

A special need exists for many modern Web and Mobile applications to enable unauthenticated access, because creating authentication barrier very often discourages users from trying a new application. Such applications would allow it to a limited set of functionalities for some time and then once users decide to join in, only authenticated access will be used.

Introduction

This tutorial aims to demonstrate how AWS Amplify can be used to create serverless applications supporting both authenticated or/and unauthenticated (anonymous) access. AWS Amplify automates and significatly simplifies the deployment of the serverless service components in the cloud. Many examples* for authenticated access with Amplify can be found in AWS documentation, however the detailed explanation about how to enable unauthenticated access using Amplify are really hard to find** (as of September 2021). Thus this document is an attempt to fill this gap.

With the help of Amplify two React applications will be configured to use AWS Cognito, AppSync and DynamoDB services, then the required services will be deployed in the AWS cloud and finally they will be hosted in S3 as static web sites. The first web site allows teachers to enter exam results and teachers will have to use a pre-provisioned Cognito account. The second application can be used by students to view the exam results and no authentication will be required at all.

Finally, the tutorial demonstrates another cool feature of GraphQL, called subscriptions. Subscriptions allow clients to listen to real-time messages from the server. The client connects to the server with a bi-directional communication channel using the WebSocket protocol and sends a subscription query that specifies which event it is interested in. When an event is triggered, the server executes the stored GraphQL query, and the result is sent back to the client using the same communication channel and the data on a page can be updated automatically.


* Examples:

** The following docs mention unauthenticated method, but do not provide full solution:

Demo of the app

This video shows both apps in use. The teacher will authenticate and will start entering the exam results. A student will use another app and no authentication will be needed. The content of the student app will be refreshed automatically as soon as new records will be added.

Demo of Teacher and Student apps side by side

Demo of the « Teacher » and the « Student » apps side by side

List of AWS Services and Tools used in this tutorial

AWS Services

  • S3 for hosting web sites built with React
  • IAM Policies and Roles
  • Cognito, both User and Identity Pools, for authentication and identity management
  • AppSync to create GraphQL driven API for application data manipulation
  • DynamoDB for storing application data
  • CloudFormation is used by Amplify to deploy services
  • Lambda is used by Amplify to update IAM Roles

AWS Tools

  • Amplify
  • AWS CLI

Building the Teacher app which uses Cognito for authentication

Overview of the steps

  1. Create a fully functional React app, supporting data models
  2. Add the configuration of AWS services to the app (amplify init, amplify add api)
  3. Provision cloud resources (amplify push)
  4. Update the app code to use AWS provided Auth UI and to store data in Dynamo DB
  5. Deploy the app (amplify add hosting, amplify publish)
  6. Enable unauthenticated access

Step 1: Create fully functional React app, supporting data models

  • Pre-requisites: Node and npm installed
  • Create a new single-page React application. At the end of this step you should have the « Teacher » React application running locally.
    npx create-react-app teacher-app
    cd teacher-app
    npm start
  • Replace the content of the App.js file with the code from the Teacher_local_App.js file.
  • Check the app: fill in the form and start adding the data. The app should be functional, but your input won’t be saved anywhere.

Step 2: Add configuration of AWS services to the « Teacher » app

  • If you will use Amplify for the first time, Amplify CLI should be installed and configured as per Getting started tutorial: sudo npm install -g @aws-amplify/cli amplify configure
  • Initialize new project with amplify init. Default values can be used during the initialization, but when asked to choose AWS profile, you might want to use your custom AWS profile, created specifically for your Amplify projects in the previous step.
  • Create ‘app-schema.graphql‘ file in the ‘src‘ folder. The file should have the following content:
type Results @model @auth(rules: [
        { allow: owner },
        { allow: public, provider: iam, operations: [read] }
    ]) {
  id: ID!
  student: String!
  grade: String!
}

type Exam @model @auth(rules: [
        { allow: owner },
        { allow: public, provider: iam, operations: [read] }
    ]) {
  id: ID!
  subject: String!
  date: String!
  teacher: String!
}
  • Add GraphQL API with amplify add api. Two authorization types should be added: Cognito User Pool first (thus it will become a default one) and IAM. At the end, type ‘./src/app-schema.graphql‘ as a path to the schema file. Click here to see the full log of the amplify add api command.

Step 3: Provision cloud resources and create the admin account for teachers

  • Execute ‘amplify push‘ command to provision all cloud resources and confirm all default parameters.
  • In order to create a new user, get the user pool id first with the following command: aws cognito-idp list-user-pools --max-results 10
  • Take the Id value from the output of the previous command and put the value in the command below. Also put any of your working email accounts as value for the email.

aws cognito-idp admin-create-user --username teacher \
--user-attributes Name=email,Value=EMAIL Name=phone_number,Value="+15555551212" \
--user-pool-id USERPOOLID --temporary-password tempmdp0007

Step 4: Update app code to use AWS provided Auth UI and to store data in Dynamo DB

  • Install the main Amplify library and the UI libraries
npm install aws-amplify
npm install @aws-amplify/ui-react
npm install @aws-amplify/ui-components
  • Add the following three lines to the ‘index.js‘ file in your application ‘src‘ folder
import Amplify, { Auth } from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);
  • Replace the content of App.js with the code in the file Teacher_final_App.js
    The Teacher app uses the UI components provided by Amplify. For this particular application, the Sign-Up option has been disabled, because the teacher account has been already created and we would not want anyone who has access to this application to be able to create another account.

Step 5: Publish the app

Use the two commands below. When adding hosting, choose HTTP with S3 option

amplify add hosting
amplify publish

Step 6: Enable unauthenticated access

When running ‘auth update’ command, choose ‘Walkthrough all the auth configurations’, then ‘User Sign-Up, Sign-In, connected with AWS IAM controls’ and finally confirm with yes when you get this prompt ‘Allow unauthenticated logins?’

amplify auth update
amplify push

Click here to see the full log of the amplify auth update command.

Building the Student app which uses unauthenticated access to the AppSync

Overview of the steps

  1. Create the student app
  2. Fetch upstream backend environment definition from the cloud and update the local environment to match that definition (amplify pull)
  3. Modify the student app code. The teach app is used here as a basis, with the following modifications:
    • remove form definitions from the page, as user input is not required
    • remove the authentication UI
    • fetch the data using IAM unauthenticated method
  4. Publish the app manually using S3 hosting

Step 1: Create the student app

    npx create-react-app student-app
    cd student-app
    npm start
  • First, execute amplify pull command in the project folder. Click here to see the full log of the amplify pull command
  • Next step is to go to AWS Console, and find in the AppSync service defintion of the student app. In the ‘Getting Started’ section you can find the command to generate GraphQL documents (queries, mutations, and subscriptions), similar to this:
    amplify add codegen --apiId acz7jy5pszerbhuwlqcksn276e

Use the default parameters, when executing ‘amplify add codegen‘ command

  • Install default Amplify packages and authentication UI libraries with ‘npm install aws-amplify
  • Add the following three lines to the ‘index.js‘ file in your application ‘src‘ folder
import Amplify, { Auth } from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);

Step 3: Modify the student app code

  • Replace the content of the ‘App.js‘ file with the code from the file Student_App.js
  • Note how the data is fetched now using IAM unauthenticated method const fetchedExamResults = await API.graphql({ query: listResults, authMode: 'AWS_IAM' });
  • This app demonstrates also the subscription capability of GraphQL. The code below subscribes to the new record creation events and when it happens, the data will be reloaded
const subscriptionUpdateSHL = API.graphql(
    {
      query: onCreateResults,
        operationName: 'onCreateResult',
        authMode: 'AWS_IAM'
      }
      ).subscribe({
        next: ({ provider, value }) => {
          console.log('Subscription worked!!!');
          fetchExamResults();
      },
        error: (error) => console.log('Error subscribing...', JSON.stringify(error)),
});

Step 4: Publish the student app manually

The student app has to be published manually, because only single hosting can be added to an Amplify project and it has been used for the Teacher app. Here is what needs to be done:

  • Create an S3 bucket
  • Build the React app (npm run build)
  • Upload all folders and files located inside ‘build’ folder from your React project to the new bucket
  • Enable public access and update bucket policy as explained in this document
  • Enable ‘Static website hosting’ from bucket properties

Commentaires :

A lire également sur le sujet :