Front-End Web & Mobile

Using AWS Amplify in AWS GovCloud (US) Regions

In this blog post, we’ll explain how using AWS Amplify in AWS GovCloud (US) Regions differs from AWS Regions. Then, we’ll walk through moving a workload from an AWS Region to AWS GovCloud (US). We’ll be assuming you wish to build a serverless web application based on modern frameworks, such as ReactJS and Angular, built on AWS services, while considering service availability in AWS GovCloud (US).

The innovation speed at AWS, and our desire to provide benefits to our customers as soon as possible, sometimes leads to situations where our customers want to use a feature or service that they see in AWS Regions, but that is not yet available in our separately partitioned Regions, such as AWS GovCloud (US). Even if the service or feature is not yet available, there is likely a work around for it, such as Amplify for the AWS GovCloud Region.

Amplify support on AWS GovCloud (US)

Amplify is a set of purpose-built tools and features that lets front-end web and mobile developers quickly and easily build full-stack applications on AWS. This includes the flexibility to leverage the breadth of AWS services as your use cases evolve. Some of these tools and features are available in AWS GovCloud (US), but feature set availability varies.

Amplify Libraries (SDKs)

Amplify provides open-source libraries to connect to back-end AWS services, such as Amazon API Gateway,  Amazon Simple Storage Service, and other database services. Amplify provides libraries for popular frameworks, such as JavaScript (Angular, React, etc.) and Mobile (iOS, Android, Flutter).

  • How it differs for AWS GovCloud (US):
    Amplify libraries can be used in your application for the services available in AWS GovCloud. However, not all services are available in AWS GovCloud. For a full list of available services in AWS GovCloud, refer to the Services in AWS GovCloud (US) Regions User Guide.

Amplify CLI (Toolchain)

Amplify provides an open-source CLI to create and configure AWS services for use in and alongside your development environment. The CLI uses Infrastructure as Code (IaC) to create the AWS resources via AWS CloudFormation. This lets you extend the AWS services via additional CloudFormation components.

    • How it differs for AWS GovCloud (US):
      The Amplify CLI is not currently supported in AWS GovCloud. Therefore, it can’t be used to deploy services even if they are available in the AWS GovCloud region. There is an open issue for requesting AWS GovCloud support for the Amplify CLI.

Amplify UI Components

Amplify provides an open-source toolkit that supplies drop-in and configurable UI components for some AWS services (auth, storage, chat), supporting mobile and JavaScript based frameworks, such as React and Angular.

Amplify Studio

The Amplify Studio (formerly Amplify Admin UI & Amplify Hosting) provides a visual interface for modeling data, as well as adding authentication, authorization, and management of users and groups.

    • How it differs for AWS GovCloud (US):
      Amplify Studio, Amplify Admin UI & Amplify Hosting are not available in the AWS GovCloud regions.

Prerequisites

The following sections are a walkthrough of deploying a solution with Amplify in an AWS Region, and moving the solution to an AWS GovCloud (US) Region. This requires you to have an account in an AWS Region, and then another account in an AWS GovCloud (US) Region with the correct access. The following resources will help you obtain the necessary prerequisites.

A common Amplify Architecture in an AWS Region

An architecture diagram showing a common Amplify Architecture in AWS Region. This shows an end user making a request to an application that uses various AWS services.

An architecture diagram showing a common Amplify Architecture in an AWS Region.

Since we’ll be moving the solution to an AWS GovCloud (US) Region from an AWS Region, we should first understand the architecture in an AWS Region. The main components of a common Amplify architecture in an AWS Region are:

  1. Front-end Application – This is the front-end delivered to the user’s browser. It will typically flow through an Amazon CloudFront distribution. This isn’t necessarily only because of the Content Delivery Network (CDN) capabilities of CloudFront, but also because of the ability to apply custom domains, caching, edge processing, security (WAF), and multiple origin back-ends. In the simplest use case, Amazon S3 is the origin of the front-end application, which is accessible from the CloudFront distribution and not open to the end user browser.
  2. Authentication Source/Broker – Amazon Cognito can serve as an OIDC authentication source by providing user and group management, or it can broker requests to an existing back-end IDP. In modern client-side web applications, the application code will facilitate direct calls to the Amazon Cognito endpoint to perform authentication, securely retrieve and store tokens, and refresh those tokens as applicable.
  3. REST API – The API endpoint is serviced by Amazon API Gateway, and it interacts with the end user via REST calls made directly from the web application code running in the user’s browser. The web application code will typically send along an Authorization header (for example, a token supplied by Amazon Cognito) so that the API endpoint and/or back-end business logic (such as an AWS Lambda function) can authorize the user for the application that they want to perform.

Deploying the architecture in an AWS Region

You can deploy the architecture shown above in an AWS Region by using the Amplify CLI. See the Amplify Docs getting started guide for details. In general, the steps to deploy the above architecture are as follows.

  1. Create a web application with your framework of choice, such as ReactJS, Angular or Vue.  For our example, we will use ReactJS.  You can follow the React Getting Started Guide to create a React application, install and configure the amplify CLI, and install Amplify libraries.
  2. To initialize your project as an Amplify project, switch to the root of your project directory and run the command: amplify init
    1. This will create some project resources in your AWS account (controlled by the AWS profile that you’re using in your local development environment).
    2. This will also create a file called aws-exports.js in your project directory that contains the configuration for each of the AWS services that you add through Amplify CLI. This will include regional endpoints; thus, it can be updated based on different environments for a “plug and play experience” as you move through environments. A sample aws-exports.js example, which is similar to the one that will be created in the following steps, looks like this:
const awsmobile = {
    "aws_project_region": "us-east-1",
    "aws_cognito_identity_pool_id": "us-east-1:-------------",
    "aws_cognito_region": "us-east-1",
    "aws_user_pools_id": "us-east-1_---------",
    "aws_user_pools_web_client_id": "--------",
    "oauth": {},
    "aws_cognito_signup_attributes": [
        "EMAIL"
    ],
    "aws_cognito_mfa_configuration": "OFF",
    "aws_cognito_mfa_types": [
        "SMS"
    ],
    "aws_cognito_password_protection_settings": {
        "passwordPolicyMinLength": 8,
        "passwordPolicyCharacters": []
    },
    "aws_cognito_verification_mechanisms": [
        "EMAIL"
    ],
    "aws_dynamodb_all_tables_region": "us-east-1",
    "aws_dynamodb_table_schemas": [
        {
            "tableName": "dynamo-----dev",
            "region": "us-east-1"
        }
    ],
    "aws_cloud_logic_custom": [
        {
            "name": "api-----",
            "endpoint": "https://---------execute-api.us-east-1.amazonaws.com/dev",
            "region": "us-east-1"
        }
    ]
};
export default awsmobile; 

Example: a generated aws-exports.js file from the amplify CLI

  1. reate the authentication component: amplify add auth
    1. This will create an Amazon Cognito User and Identity Pool. If you want to federate with an existing Identity Provider (IDP), you can check out the Auth0 example in the Amplify documentation.
    2. At this point, you can add authentication workflows to your application. The easiest way is to use Pre-Built UI components, but you can also call authentication APIs directly.
import { Amplify } from 'aws-amplify';

import { withAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import awsExports from './aws-exports';
Amplify.configure(awsExports);

function App({ signOut, user }) {
  return (
    <>
      <h1>Hello {user.username}</h1>
      <button onClick={signOut}>Sign out</button>
    </>
  );
}

export default withAuthenticator(App);
    1. For signing in with an existing IDP, you can check out the Advanced Workflows section. Essentially, you will leverage calls to Auth.federatedSignIn, which will create the redirects to Amazon Cognito and your backend IDP (A useful 3rd party example).
  1. Create the REST API: amplify add api.
    1. The Getting Started guide will take you through creating a REST API.   For our example, we’ll use the Serverless ExpressJS function template, which will create an end-to-end API with API Gateway, business logic (Lambda) and data tier.  The Complete Guide to User Authentication with the Amplify Framework is a useful third-party example.
Shows the option to select the Serverless ExpressJS function template when creating a REST API in the amplify add API command, which will create a sample logic and data tier for your API.

Selecting the Serverless ExpressJS function template.

    1. Example code to get and post data to the REST API using Amplify Libraries will look something like the following (taken from Amplify Docs for Fetching data):
import { useState } from 'react';
import { Amplify, API } from 'aws-amplify';
import { withAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import awsExports from './aws-exports';
2	
Amplify.configure(awsExports);
3	
const apiName = '<your api id>';
const path = '/items';
const myInit = {
  headers: {
    // Add your headers here
  },
  response: true,
  queryStringParameters: {
    // Add your query string parameters here 
  },
};

function App({ signOut, user }) {
  const [fetchedData, setFetchedData] = useState("Nothing");
  const addData = () => {
    API.put(apiName, path, {
      body: {
        "name": "cat",
        "description": "a furry friend"
      }
    }).then(response => {
      console.log(response);
    }).catch(err => console.log(err));
  }
  const getData = () => {
    API
      .get(apiName, path + "/cat", myInit)
      .then(response => {
        console.log(response);
        if (response.data.length > 0)
          setFetchedData("Found data: " + JSON.stringify(response.data[0]));
      })
      .catch(error => {
        console.log(error.response);
      });

  };

  return (
    <>
      <h1>Hello {user.username}</h1>
      <button onClick={signOut}>Sign out</button> | 
      <button onClick={getData}>Get Data</button> | 
      <button onClick={addData}>Set Data</button>
      <br />
      {fetchedData}
    </>
  );
}
export default withAuthenticator(App);
  1. 5 Host the web application: amplify add hosting
    1.  The hosting category will provide several options for deploying the web application. At this point, it should be considered that CloudFront and Amplify Hosting are not available in AWS GovCloud (US). They can be used in a hybrid architecture where the front-end is in an AWS Region, and the back-end is in an AWS GovCloud (US) Region. If the requirements are to host the front-end application in the AWS GovCloud (US) Region and since CloudFront or Amplify Hosting are not in the AWS GovCloud (US) Region at this time, a workaround will be needed, which will be covered later in this post.
      1. Amazon S3 hosting
        This lets an end user directly access the web application endpoint from an Amazon S3 endpoint. This is recommended only for non-prod deployments, and it still should include the best practices for securing least privilege access.
      2. CloudFront + Amazon S3 hosting
        This is reflected in the above diagram, and it’s the recommended approach for production deployments in the AWS Region.
      3. Amplify Hosting
        The Amplify Console provides a fully-managed hosting solution for your web application, including built-in CI/CD pipelines. It also supports the deployment of the back-end services that you created through Amplify.

Deploying a hybrid solution

Now that we have an application that was built with Amplify on an AWS Region, let’s consider that you want to deploy this same architecture in AWS GovCloud (US), but you want the benefits of using Amazon CloudFront. In this solution, we’ll make the necessary changes to have the back-end resources point to an AWS GovCloud (US) Region, while leaving the front-end resources in an AWS Region.

The following image shows an example folder structure for an Amplify project:

This shows a folder structure of an Amplify project. The root of the project with a folder called Amplify with sub folders of .config, #current-cold-back-end and back-end. The back-end folder opened showing a sub folder with it in and sub folders of those folders.

An example folder structure of an Amplify project.

Here are the tasks required to reuse the CloudFormation template created by the Amplify project:

  1. Create an Amazon S3 bucket in the GovCloud account
The UI for Creating an Amazon S3 bucket. Showing the Bucket Name and AWS Region. Where the Bucket Name is globally unique and the AWS Region is set to an AWS GovCloud Region.

The UI for Creating an Amazon S3 bucket. Showing the Bucket Name and AWS Region.

  1. Copy the CloudFormation template structure in a local folder.

In this example, there’s a top-level folder called govcloud_modified_templates and then a sub-folder for each category: api, auth, function and storage.

A local folder for storing modified CloudFormation templates Then, in the Amplify project, find the awscloudformation\build folder and copy each CloudFormation template to the corresponding local folder.

A local folder for storing modified CloudFormation templates

Then, in the Amplify project, find the awscloudformation\build folder and copy each CloudFormation template to the corresponding local folder.

This is where the Amplify CloudFormation templates will be copied to modify them to work in the GovCloud regions.

Copying CloudFormation templates from the amplify folder to your local folder.

  1. Next, modify the root-cloudformation-stack.json template in the local folder so that each nested template points to the URI for the GovCloud Amazon S3 Bucket.

Modify the TemplateURL property of each nested CloudFormation file.

  1. In each local template file, modify any “arn:aws” resources to instead use “arn:aws-us-gov”.
Update the arn to use the aws-us-gov region.

Update the arn to use the aws-us-gov region.

  1. For the API template, the following properties must be added, due to lack of support for edge APIs in GovCloud:
Add required properties to the API CloudFormation template.

Add required properties to the API CloudFormation template.

  1. Copy the modified files to the Amazon S3 bucket, inside of amplify-cfn-templates folder, making sure that each folder and file matches the TemplateURL property for each nested stack in the root CloudFormation template.
Upload modified templates to the GovCloud Amazon S3 bucket that was previously created.

Upload modified templates to the GovCloud Amazon S3 bucket that was previously created.

  1. For any Lambda function, the zipped code file must be uploaded into an amplify-builds folder.
Shows the amplify-builds folder where the Lambda function code should be placed.

Upload the Lambda function code to a amplify-builds folder.

  1. Create the stack via the CloudFormation console using the Amazon S3 URL for the root-cloudformation-stack.json file, which will make sure that all of the nested stacks run as well.  The stack name must be named with the following pattern: amplify-<appname>-<environment>-<5 digit number>, where <environment> is an abbreviation such as dev, test, or prod.
Create the CloudFormation stack.

Create the stack using the URL to the root-cloudformation-stack.json file.

Once the CloudFormation template status changes to CREATE_COMPLETE, then test the application components using the GovCloud resources by updating the aws-exports.js file to point to those newly created resources.

Optionally, the Amplify configuration can be exported to an AWS Cloud Development Kit (AWS CDK) project for developing customized deployment pipelines, as outlined in the “Export Amplify backends to CDK and use with existing deployment pipelines” post.

Deploying solely on AWS GovCloud (US)

If you’ve been following along, then you would have an architecture that is using AWS GovCloud (US) for the back-end services (Amazon Cognito and API Gateway). However, it will still be leveraging an AWS Region for the front-end. This may be acceptable depending on your compliance and security requirements (most likely the data protection requirements).

An architecture diagram showing a common Amplify Architecture across in AWS Region for the front-end and then using AWS GovCloud (US) for the back-end services. This shows an end user making a request to an application that uses various AWS services.

An architecture diagram showing a common Amplify Architecture across in AWS Region for the front-end and then using AWS GovCloud (US) for the back-end services.

Remember that the hybrid solution has the front-end hosting (#1 in the diagram – CloudFront and Amazon S3), typically only application code (HTML/JS/static content), and not storing application/sensitive data. The use of the “hybrid solution” is something you must review with your compliance team and your Authorizing Official to see if it’s sufficient.

If a hybrid solution is insufficient, then you have the following options, since CloudFront isn’t available in the AWS GovCloud (US) regions:

  1. Follow the AWS GovCloud (US) user guide for Tips for setting up CloudFront where the S3 bucket would be located in AWS GovCloud (US) and a custom origin server would be used to point to the S3 bucket.
    1. Note that CloudFront would be outside of the AWS GovCloud (US) and not inside the ITAR boundary. This may be acceptable, if not, see the other options.
  1. Use another AWS service or custom proxy to provide that front-end entry point for your hosted web application that proxies requests to Amazon S3.
    1. API Gateway – This is essentially using API Gateway as a proxy to Amazon S3. You still get many of the usability benefits that CloudFront offers, but with a service supported in AWS GovCloud (US). The following resources will help you understand how to do this.
      1. Create a REST API as an Amazon S3 proxy
      2. There is also this third-party post, “How to Proxy an S3 Static Website”, which gives more details on the implementation.
    1. AWS ALB + Lambda – this option uses an AWS ALB with Lambda as the “proxy” layer. It’s more complicated, because there is some code that must be written for the proxy layer. Moreover, AWS doesn’t provide any specific examples for how to do this. The following resources will help you understand how to do this.
      1. AWS Lambda with Application Load Balancer
      2. How Elastic Load Balancing Differs for AWS GovCloud
        ALB doesn’t support all of the features in AWS GovCloud (US), so you will want to consider that before implementation.
  1. Use Amazon S3 as the hosting endpoint. This would only be recommended for non-public sites (typically internal applications), whereby you have placed appropriate security and least-privilege access protections on the Amazon S3 endpoint.

Cleaning up

Depending on how you set up this architecture, there could be some unused resources. For example, if you deployed in an AWS Region, and then made the necessary changes to move to the AWS GovCloud (US) Region, the AWS Region resources will likely still be there. Furthermore, if you followed along just to see how this worked, then there will be resources that you must clean up.

In an AWS Region, you can remove an Amplify project with the Amplify CLI delete command or through the Amplify console. You can also find the CloudFormation stack generated by Amplify and delete it by following the Deleting a stack on the AWS CloudFormation console instructions. You’ll want to look in the AWS Region and the AWS GovCloud (US) Region for the Cloud Formation stacks.

If you made the necessary changes to solely deploy on AWS GovCloud (US), then you must remove any resources that you used to replace CloudFront.

Next steps

At this point, you should have an application that was built with Amplify on AWS GovCloud (US). There are a couple of things to consider when going forward.

You should consider adding authentication to the web application. In many modern web-based browsers, this logic is included in the application code, whereby the code will check if a user is authenticated, and if not, then either:

  1. Give user access to only non-authorized content with an option to authenticate, or
  1. Have the landing page (which must be unauthenticated accessible) automatically route the user to the IDP for authentication, have a call-back page that processes the authentication token, and then redirects the user to the authenticated application.

The Amazon Cognito Authentication Flows page can be used as a starting point resource. As well as this walkthrough guide for Integrating IDP Sign In with Cognito and Okta.

Conclusion

This post went over the available functionality of Amplify in AWS GovCloud (US).  It walked through creating an Amplify application starting in an AWS region and moving it to AWS GovCloud (US) with options for addressing the workload’s requirements.

At AWS, we strive to understand and meet the needs of our customers. If you would like Amplify to be more fully supported on AWS GovCloud (US), then comment on this post and reach out to your AWS account team or submit a feature request in the appropriate Amplify Github project.

Finally, consider reaching out to your AWS Solution Architect when a feature or service is not yet available in AWS GovCloud (US), as there may be a work-around for it.

Authors:

Tyler Replogle

Tyler Replogle is a Senior Solutions Architect at AWS in the World-Wide Public-Sector group, where he works with US Federal Partners to enable their success on AWS. He enjoys building and has found ways to connect with his three daughters through building with Lego, Minecraft, coding, and now Roblox.

Jason Hoog

Jason Hoog is a Senior Solutions Architect at AWS, where he works with global customers to enable their success on AWS. He is also a member of the Mobile Technical Field Community.