├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── amplify_code ├── amplify │ ├── #current-cloud-backend │ │ ├── amplify-meta.json │ │ ├── auth │ │ │ ├── myamplifyapp84642f50 │ │ │ │ ├── myamplifyapp84642f50-cloudformation-template.yml │ │ │ │ └── parameters.json │ │ │ └── userPoolGroups │ │ │ │ ├── parameters.json │ │ │ │ ├── template.json │ │ │ │ └── user-pool-group-precedence.json │ │ └── backend-config.json │ ├── backend │ │ ├── amplify-meta.json │ │ ├── auth │ │ │ ├── myamplifyapp84642f50 │ │ │ │ ├── myamplifyapp84642f50-cloudformation-template.yml │ │ │ │ └── parameters.json │ │ │ └── userPoolGroups │ │ │ │ ├── parameters.json │ │ │ │ ├── template.json │ │ │ │ └── user-pool-group-precedence.json │ │ ├── awscloudformation │ │ │ └── nested-cloudformation-stack.yml │ │ └── backend-config.json │ └── team-provider-info.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── aws-exports.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js ├── amplify_pictures ├── AmplifyAddAuth.png ├── AmplifyAddHosting.png ├── AmplifyAddUserPool.png ├── AmplifyAttachPolicy.png ├── AmplifyAuthPerms.png ├── AmplifyAuthRole.png ├── AmplifyBlankApp.png ├── AmplifyCLIConfig.png ├── AmplifyCognitoGroup.png ├── AmplifyCognitoIdentities.png ├── AmplifyCognitoIdentityID.png ├── AmplifyCognitoUser.png ├── AmplifyConfigureEnter.png ├── AmplifyDeviceConnected.png ├── AmplifyEmptyApp.png ├── AmplifyIAMAddUser.png ├── AmplifyIAMPolicy.png ├── AmplifyIAMSuccess.png ├── AmplifyIAMTags.png ├── AmplifyIOTPolicy.png ├── AmplifyIncomingMsg.png ├── AmplifyInit.png ├── AmplifyMsgReceived.png ├── AmplifyParentStack.png ├── AmplifyPublish.png ├── AmplifyPush.png ├── AmplifySendMsg.png ├── AmplifySentMsg.png ├── AmplifySignInPage.png ├── AmplifySignInUser.png └── AmplifyURL.png ├── iot_code └── DemoProject │ ├── include │ ├── README │ └── secrets.h │ ├── lib │ └── README │ ├── platformio.ini │ ├── src │ └── main.cpp │ └── test │ └── README └── iot_pictures ├── IoT Core Add device to Registry.png ├── IoT Core Attach Policy Choose Pol.png ├── IoT Core Attach Policy.png ├── IoT Core Certificate Created.png ├── IoT Core Certificates.png ├── IoT Core Confirm Cert.png ├── IoT Core Create Policy with any resource in account.png ├── IoT Core Create a Single Thing.png ├── IoT Core How to Get AccountID.png ├── IoT Core How to Get Region.png ├── IoT Core Manage Tab.png ├── IoT Core Secure Tab.png ├── IoT Core Skip Attach Policy.png ├── IoTConsoleTestPub.png ├── IoTConsoleTestSub.png ├── IoTConsoleTestSubPage.png ├── IoTCorePolicy.png ├── IoTTestSub.png ├── PlatformIO AJ Library.png ├── PlatformIO Bottom Bar.png ├── PlatformIO Install.png ├── PlatformIO MQTT Library.png ├── PlatformIO New Project.png ├── PlatformIO Project Options.png ├── ProjectArch.png ├── ProjectArch2.png ├── ProjectArch3.png ├── ProjectArchV3.png ├── ProjectArchV4.png ├── Serial Monitor.png └── Successful Flash.png /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS End-to-End IoT Amplify Application in the Cloud 2 | 3 | ## Table of Contents 4 | [Introduction](#introduction) 5 | [Prerequisites](#prerequisites) 6 | [Section I : IoT Setup](#Section-I--IoT-Setup) 7 | - [Setting Up Your Device in AWS IoT Core](#Setting-Up-Your-Device-in-AWS-IoT-Core) 8 | - [Configuring the ESP32](#Configuring-the-ESP32) 9 | - [Testing Your IoT Setup](#Testing-Your-IoT-Setup) 10 | 11 | [Section II : Amplify Setup](#Section-II--Amplify-Setup) 12 | - [Setting Up AWS Amplify Application in the Cloud](#Setting-Up-AWS-Amplify-Application-in-the-Cloud) 13 | - [Creating Your AWS Amplify Application](#Creating-Your-AWS-Amplify-Application) 14 | - [Add Authentication To Your Application](#Add-Authentication-To-Your-Application) 15 | - [Using the AWS Amplify PubSub Library to Communicate with AWS IoT Core](#Using-the-AWS-Amplify-PubSub-Library-to-Communicate-with-AWS-IoT-Core) 16 | - [Deploying Your Web Application](#Deploying-Your-Web-Application) 17 | 18 | ## Introduction 19 | 20 | In this demo, you will learn how to build a hosted web application in the cloud that communicates with your [Espressif ESP32](https://www.espressif.com/en/products/devkits/esp32-devkitc/overview) development board via the MQTT protocol. By following the below guide, you should be able to: 21 | 22 | 1. Register a device in AWS IoT Core and establish a secure policy for that device 23 | 2. Configure your ESP32 to publish and subscribe to topics in the AWS cloud using the MQTT protocol 24 | 3. Build a web application in the cloud using AWS Amplify that bidirectionally communciates with your ESP32 25 | 4. Apply this basic messaging application to fit your needs 26 | 27 | By following this tutorial, you will setup the below architecture. This will make more sense as we go along. 28 | 29 | **Note: IMPORTANT** This is a demo only. This is not to be used in a production environment as-is. Please use this to learn and for helping build a demo or PoC only. 30 | 31 | ![AWS End-To-End IoT Web Application](./iot_pictures/ProjectArch3.png) 32 | 33 | ## Prerequisites 34 | 35 | In order to get started, make sure you have the following: 36 | 37 | 1. A Mac/PC with admin access and internet connectivity 38 | 2. An AWS Account. A tutorial can be found [here.](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/) 39 | 3. An ESP32 DevKit. You can find them here: https://www.amazon.com/gp/product/B0811LGWY2/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1 40 | 4. A microUSB cable to connect the ESP32 to your computer 41 | [MicroUSB to USB-C cable](https://www.amazon.com/gp/product/B01LONQ7R6/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1) 42 | [MicroUSB to USB cable](https://www.amazon.com/AmazonBasics-Male-Micro-Cable-Black/dp/B07232M876/ref=sr_1_1_sspa?dchild=1&keywords=micro+usb+to+usb&qid=1595002180&s=electronics&sr=1-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzR0ZORUgxWTFHNVZEJmVuY3J5cHRlZElkPUEwODMyMjA2MTFMNzVBSlNUSFdEViZlbmNyeXB0ZWRBZElkPUEwODUwMDczM0RVWE5FVTZWSkRQViZ3aWRnZXROYW1lPXNwX2F0ZiZhY3Rpb249Y2xpY2tSZWRpcmVjdCZkb05vdExvZ0NsaWNrPXRydWU=) 43 | 5. The AWS CLI installed in your terminal or command shell. Follow the below tutorial on how to install the AWS CLI for your computer's operating system: 44 | https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html 45 | 46 | We will break down this tutorial into two main sections, an IoT section and a web app section. First, let's look at the IoT component. 47 | 48 | # Section I : IoT Setup 49 | 50 | This section will cover everything you need to setup your ESP32 to communicate with [AWS IoT Core](https://aws.amazon.com/iot-core/). In order to do so, we must first register our device on AWS. In AWS IoT Core, devices are called "things". We will setup a "thing" in AWS to keep track of our device and its security permissions. 51 | 52 | ## Setting Up Your Device in AWS IoT Core 53 | 54 | 1. From the [AWS Console](https://console.aws.amazon.com/console/home), navigate to AWS IoT Core. 55 | 56 | 2. If it is your first time using IoT Core, hit “Get started” 57 | 58 | 3. On the left panel, expand the “Manage” tab and click “Things” 59 | ![AWS IoT Core Manage Tab](./iot_pictures/IoT%20Core%20Manage%20Tab.png) 60 | 61 | 4. Click “Create a single thing” ![AWS IoT Core Create a Single Thing](./iot_pictures/IoT%20Core%20Create%20a%20Single%20Thing.png) 62 | 63 | 5. Give your device a name (In this demo we will use the name ESP32 which is referenced in many other steps. If you wish to use a different name, replace ESP32 with your name in the following steps) and click “Next” ![AWS IoT Core Add Device to Registry](./iot_pictures/IoT%20Core%20Add%20device%20to%20Registry.png) 64 | 65 | 6. Click “Create certificate” 66 | 67 | 7. Download the certificate (first option), the private key (third option), and the root CA 1 for AWS Iot (fourth option - go to external site, find “RSA 2048 bit key:” and click “Amazon Root CA 1” to download). Keep these certificates and keys in a safe place for future use. You do not need to download the public key. ![AWS IoT Core Certificate Created](./iot_pictures/IoT%20Core%20Certificate%20Created.png) 68 | 69 | 8. Click “Activate” - button should change to “Deactivate” 70 | 71 | 9. Click "Attach Policy" 72 | 73 | 10. Do not attach a policy yet, click “Register Thing” - you will be redirected to Things homepage. ![AWS IoT Core Skip Add Policy](./iot_pictures/IoT%20Core%20Skip%20Attach%20Policy.png) 74 | 75 | 11. You will need to find your account ID and region for the next step. To find your account ID, click on the tab on the top that displays your account name. Two pieces of information will be shown, “Federated Login” and “Account”. Save the number underneath “Account”, this is your account ID. Save your account ID (without hyphens) somewhere for the next step. To find your region, click on the tab just to the right of the account tab, it should display a country or state name. The bolded region is your region (ex. us-west-2). Save this region (with hyphens) somewhere for the next step. 76 | 77 | ![AWS IoT Core How to Find Account ID](./iot_pictures/IoT%20Core%20How%20to%20Get%20AccountID.png) ![AWS IoT Core How to Find Region](./iot_pictures/IoT%20Core%20How%20to%20Get%20Region.png) 78 | 79 | 12. Back in AWS IoT Core, expand the “Secure” tab on the left panel and click “Policies” ![AWS IoT Core Secure Tab](./iot_pictures/IoT%20Core%20Secure%20Tab.png) 80 | 81 | 13. Click “Create a Policy” 82 | 83 | 14. Give the policy a name and click “Advanced mode” 84 | 85 | 15. Click in the “Add statements” box and add the following code, replacing ACCOUNT_ID, REGION, SUBSCRIPTION_TOPIC_NAME, and PUBLISH_TOPIC_NAME with your account ID, Region, and topic names. 86 | ```JSON 87 | { 88 | "Version": "2012-10-17", 89 | "Statement": [ 90 | { 91 | "Effect": "Allow", 92 | "Action": "iot:Connect", 93 | "Resource": "arn:aws:iot:REGION:ACCOUNT_ID:client/${iot:Connection.Thing.ThingName}" 94 | }, 95 | { 96 | "Effect": "Allow", 97 | "Action": "iot:Subscribe", 98 | "Resource": "arn:aws:iot:REGION:ACCOUNT_ID:topicfilter/SUBSCRIPTION_TOPIC_NAME" 99 | }, 100 | { 101 | "Effect": "Allow", 102 | "Action": "iot:Receive", 103 | "Resource": "arn:aws:iot:REGION:ACCOUNT_ID:topic/SUBSCRIPTION_TOPIC_NAME" 104 | }, 105 | { 106 | "Effect": "Allow", 107 | "Action": "iot:Publish", 108 | "Resource": "arn:aws:iot:REGION:ACCOUNT_ID:topic/PUBLISH_TOPIC_NAME" 109 | } 110 | ] 111 | } 112 | ``` 113 | 114 | ![AWS IoT Core Policy](./iot_pictures/IoTCorePolicy.png) 115 | Note: your region should be formatted the same way it appears in the AWS console (ex. us-west-2). However, your Account ID should not include any hyphens or your device will not be able to connect to AWS IoT Core. 116 | 117 | This policy allows devices with this attached policy to connect to AWS and subscribe, receive, and publish messages to topics in AWS IoT Core. This allows our IoT device to connect because we have registered it as a "thing" in AWS IoT Core and attached the above policy. It will also allow other services to publish to the same topics, as we will see later. 118 | 119 | 16. Click “Create” - you will be redirected to Policies homepage. 120 | 121 | 17. On the left panel, expand the “Secure” tab and click “Certificates” ![AWS IoT Core Certificates Homepage](./iot_pictures/IoT%20Core%20Certificates.png) 122 | 123 | 18. Select the certificate you created for your device (this can be checked by clicking on the certificate and clicking on the “Things” tab, your device should be displayed). ![AWS IoT Core Certificate Confirmation](./iot_pictures/IoT%20Core%20Confirm%20Cert.png) 124 | 125 | 19. Click “Policies” 126 | 127 | 20. Click the “Actions” drop down in the top right of this dashboard, click “Attach Policies” ![AWS IoT Core Attach Policy to Certificate](./iot_pictures/IoT%20Core%20Attach%20Policy.png) 128 | 129 | 21. Check the box next to the policy you made in previous steps and click “Attach” ![AWS IoT Core Attach Policy to Certificate](./iot_pictures/IoT%20Core%20Attach%20Policy%20Choose%20Pol.png) 130 | 131 | Now that we have configured our ESP32 as a "thing" in AWS IoT Core, we must tell the ESP32 where and how to send messages. To do this, we will be using the [Arduino Framework](https://www.arduino.cc/) to build a small application that is flashed into the device's memory. Our application will use the MQTT protocol to send a message periodically to the topic "esp32/pub". The message will contain a timestamp and the value of a sensor on the device (Note: no sensor is needed for this to work). Follow the below steps to configure your ESP32 for AWS IoT Core. 132 | 133 | ## Configuring the ESP32 134 | 135 | In this section, we will be using the PlatformIO IDE within VS Code to flash the ESP32 with code. VS Code is a popular choice for developers and can be used for both parts of this guide. The Arduino IDE can also be used for this section but you will still need to download VS Code or another IDE for Section II. If you would like to use the Arduino IDE, you can [learn more here](https://github.com/aws-samples/aws-iot-workshop). 136 | 137 | 1. Download [VS Code](https://code.visualstudio.com/) for your OS 138 | 139 | 2. Open VS Code and click on the extensions tab on the left bar. Search “PlatformIO IDE” and choose the first option. Click install. You may need to restart VS Code to finish the installation. ![VS Code PlatformIO Install](./iot_pictures/PlatformIO%20Install.png) 140 | 141 | 3. Back in VS Code, click on the house icon in the bottom left (purple or blue bar) to navigate to the PlatformIO homepage. 142 | ![VS Code PlatformIO Bottom Nav Bar](./iot_pictures/PlatformIO%20Bottom%20Bar.png) 143 | 144 | 4. Click “New Project” ![VS Code PlatformIO New Project](./iot_pictures/PlatformIO%20New%20Project.png) 145 | 146 | 5. Give the project a name and search for “Espressif ESP32 Dev Module” under boards. Select Arduino for the Framework. Click “Finish” when done ![VS Code PlatformIO Project Setup](./iot_pictures/PlatformIO%20Project%20Options.png) 147 | 148 | 6. Once the project loads, again click on the house icon in the bottom left. Click on “Libraries” on the left panel of the PlatformIO homepage. Install two libraries, MQTT by Joel Gaehwiler and ArduinoJSON by Benoit Blanchon. Restart VS Code and the libraries should be successfully installed. 149 | 150 | ![VS Code PlatformIO MQTT Library Dependency](./iot_pictures/PlatformIO%20MQTT%20Library.png) ![VS Code PlatformIO ArduinoJSON Library Dependency](./iot_pictures/PlatformIO%20AJ%20Library.png) 151 | 152 | 7. In VS Code's file explorer, you will see your project's root directory. Click the “Include” folder in to expand it. Click the new file button near the project name to create a new file in that folder. Call the new file “secrets.h” 153 | 154 | 8. Copy and paste the following code into secrets.h: 155 | ```C 156 | #include 157 | #define SECRET 158 | #define THINGNAME "ESP32" 159 | const char WIFI_SSID[] = ""; 160 | const char WIFI_PASSWORD[] = ""; 161 | const char AWS_IOT_ENDPOINT[] = ""; 162 | // Amazon Root CA 1 163 | static const char AWS_CERT_CA[] PROGMEM = R"EOF( 164 | -----BEGIN CERTIFICATE----- 165 | // insert AWS root CA 1 cert here 166 | -----END CERTIFICATE----- 167 | )EOF"; 168 | // Device Certificate 169 | static const char AWS_CERT_CRT[] PROGMEM = R"KEY( 170 | -----BEGIN CERTIFICATE----- 171 | // insert device certificate here 172 | -----END CERTIFICATE----- 173 | )KEY"; 174 | // Device Private Key 175 | static const char AWS_CERT_PRIVATE[] PROGMEM = R"KEY( 176 | -----BEGIN RSA PRIVATE KEY----- 177 | // insert device private key here 178 | -----END RSA PRIVATE KEY----- 179 | )KEY"; 180 | ``` 181 | 182 | 9. In the above code, enter your Wifi SSID (wifi name), Wifi password, and AWS IoT endpoint. You can find your AWS IoT endpoint by clicking “Settings” on the bottom of the left pane in AWS IoT Core. You will also need to paste your root CA certification, the device certification, and the private key into the respective places in the code. Note: you do need the “-----BEGIN CERTIFICATE-----” tags. On mac, TextEdit works well for opening the key and certificate files. 183 | 184 | 10. Open the src folder by clicking on it in the file explorer tab. Replace the scaffolding code in main.cpp with the following code (note: this code is a slight adaptation from code written in an AWS blog post https://aws.amazon.com/blogs/compute/building-an-aws-iot-core-device-using-aws-serverless-and-an-esp32/ to work on PlatformIO): 185 | ```C 186 | #include 187 | #include "../include/secrets.h" 188 | #include 189 | #include 190 | #include 191 | #include "WiFi.h" 192 | 193 | // The MQTT topics that this device should publish/subscribe 194 | #define AWS_IOT_PUBLISH_TOPIC "esp32/pub" 195 | #define AWS_IOT_SUBSCRIBE_TOPIC "esp32/sub" 196 | 197 | WiFiClientSecure net = WiFiClientSecure(); 198 | MQTTClient client = MQTTClient(256); 199 | 200 | void messageHandler(String &topic, String &payload) { 201 | Serial.println("incoming: " + topic + " - " + payload); 202 | } 203 | 204 | void connectAWS() 205 | { 206 | WiFi.mode(WIFI_STA); 207 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 208 | 209 | Serial.println("Connecting to Wi-Fi"); 210 | 211 | while (WiFi.status() != WL_CONNECTED){ 212 | delay(500); 213 | Serial.print("."); 214 | } 215 | 216 | // Configure WiFiClientSecure to use the AWS IoT device credentials 217 | net.setCACert(AWS_CERT_CA); 218 | net.setCertificate(AWS_CERT_CRT); 219 | net.setPrivateKey(AWS_CERT_PRIVATE); 220 | 221 | // Connect to the MQTT broker on the AWS endpoint we defined earlier 222 | client.begin(AWS_IOT_ENDPOINT, 8883, net); 223 | 224 | // Create a message handler 225 | client.onMessage(messageHandler); 226 | 227 | Serial.print("Connecting to AWS IOT"); 228 | 229 | while (!client.connect(THINGNAME)) { 230 | Serial.print("."); 231 | delay(100); 232 | } 233 | 234 | if(!client.connected()){ 235 | Serial.println("AWS IoT Timeout!"); 236 | return; 237 | } 238 | 239 | // Subscribe to a topic 240 | client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC); 241 | 242 | Serial.println("AWS IoT Connected!"); 243 | } 244 | 245 | void publishMessage() 246 | { 247 | StaticJsonDocument<200> doc; 248 | doc["time"] = millis(); 249 | doc["sensor_a0"] = analogRead(0); 250 | char jsonBuffer[512]; 251 | serializeJson(doc, jsonBuffer); // print to client 252 | 253 | client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer); 254 | } 255 | 256 | void setup() { 257 | Serial.begin(9600); 258 | connectAWS(); 259 | } 260 | 261 | void loop() { 262 | publishMessage(); 263 | client.loop(); 264 | delay(1000); 265 | } 266 | ``` 267 | 268 | =====Code Explanation Start===== 269 | ``` 270 | WiFi.mode(WIFI_STA); 271 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 272 | 273 | Serial.println("Connecting to Wi-Fi"); 274 | 275 | while (WiFi.status() != WL_CONNECTED){ 276 | delay(500); 277 | Serial.print("."); 278 | } 279 | ``` 280 | 281 | This section of the code connects your ESP32 device to your Wifi. We use the WifiClientSecure library and the Wifi's SSID and password you set in "secrets.h" 282 | 283 | ``` 284 | Serial.print("Connecting to AWS IOT"); 285 | 286 | while (!client.connect(THINGNAME)) { 287 | Serial.print("."); 288 | delay(100); 289 | } 290 | 291 | if(!client.connected()){ 292 | Serial.println("AWS IoT Timeout!"); 293 | return; 294 | } 295 | 296 | // Subscribe to a topic 297 | client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC); 298 | 299 | Serial.println("AWS IoT Connected!"); 300 | ``` 301 | 302 | The above code connects your device to AWS IoT. We use an MQTT client to accomplish this. 303 | 304 | ``` 305 | void publishMessage() 306 | { 307 | StaticJsonDocument<200> doc; 308 | doc["time"] = millis(); 309 | doc["sensor_a0"] = analogRead(0); 310 | char jsonBuffer[512]; 311 | serializeJson(doc, jsonBuffer); // print to client 312 | 313 | client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer); 314 | } 315 | ``` 316 | 317 | This function creates a JSON (JavaScript Object Notation) document containing two values, "time" and "sensor_a0". Sensor a0 is a input port on your ESP32 that can be connected to a sensor to generate real data and store it in this JSON document. If you do not have a sensor, this is okay for now just note that the device will read one constant value. This document is then serialized and sent to AWS IoT by publishing to the "esp32/pub" topic. 318 | 319 | =====Code Explanation End======= 320 | 321 | 11. If you still have an error with your "#include" statements in main.cpp, restart VS Code and the error should disappear. 322 | 323 | 12. Next, click the checkmark icon in the bottom bar to build your PlatformIO project. 324 | ![VS Code PlatformIO Bottom Nav Bar](./iot_pictures/PlatformIO%20Bottom%20Bar.png) 325 | 326 | 13. To finish configuring the ESP32, you need to flash your code onto the device. With the board plugged in, click the arrow icon in the bottom bar to upload your code to the ESP32. ![VS Code PlatformIO Successful Flash to Device](./iot_pictures/Successful%20Flash.png) 327 | 328 | 14. To see your code in action, click the serial monitor button in the bottom bar, it looks an electrical plug. The terminal should display that your device first connected to your Wifi and then to AWS IoT. Any incoming messages on the topic “esp32/sub” will appear here. Your ESP32 should be publishing messages every so often to the topic “esp32/pub”. 329 | 330 | ![VS Code PlatformIO Serial Monitor](./iot_pictures/Serial%20Monitor.png) 331 | 332 | ## Testing Your IoT Setup 333 | 334 | 1. Now, test your IoT setup by logging back into the AWS Console and navigating to AWS IoT Core. Click "Test" on the left panel. First, we will test the topic to which your ESP32 is publishing messages. Enter "esp32/pub" into the "Subscription topic" box. Keep all of the other settings as default. 335 | 336 | ![AWS IoT Core Test Subscription Page](./iot_pictures/IoTConsoleTestSubPage.png) 337 | 338 | 2. Click "Subscribe to topic". You should now see the messages arriving from the ESP32. The messages each contain a timestamp and a sensor value. 339 | 340 | ![AWS IoT Core Test Subscription Messages](./iot_pictures/IoTConsoleTestSub.png) 341 | 342 | 3. Next, we will test your ESP32 subscribing to the topic "esp32/sub". Navigate back to the "Test" page in AWS IoT Core and this time, enter "esp32/sub" in the "Publish" section. You can write a custom message or use the default "Hello from AWS IoT Console". 343 | 344 | ![AWS IoT Core Test Publish Page](./iot_pictures/IoTConsoleTestPub.png) 345 | 346 | 4. Click "Publish to topic". Back in VS Code, you should see the message appear on the serial monitor for your device. 347 | 348 | ![VS Code PlatformIO Serial Monitor With Test Message From Console](./iot_pictures/IoTTestSub.png) 349 | 350 | Congratulations! Your ESP32 is now connected to AWS IoT Core and is able to send and receive messages to different IoT topics. Follow the steps in the following section to setup your own web application that can communicate with your ESP32. 351 | 352 | # Section II : Amplify Setup 353 | 354 | This section will cover the process of setting up an application in the cloud using [AWS Amplify](https://aws.amazon.com/amplify/). By the end of this section, you should have a working application that can send and receive messages to your ESP32 device. Using the Arduino application from the previous section, the ESP32 will be sending frequent messages that will be displayed on the web application's homepage. The application is meant to be a baseline for your use case, you can configure the front end of this application to fit your needs. 355 | 356 | AWS Amplify can be used to build mobile and web applications. In this tutorial, we will be focusing on web applications but the same concept can be applied to mobile apps as well. 357 | 358 | ## Setting Up AWS Amplify Application in the Cloud 359 | 360 | We will now setup our AWS Amplify application. Amplify is primarily configured using the [AWS Command Line Interface](https://aws.amazon.com/cli/) (CLI). Note that this tutorial was done on MacOS so you may need to adjust your commands if you are using Windows. Most of these commands came from the [AmplifyDocs](https://docs.amplify.aws/start/q/integration/react) website. We will be using the [React](https://reactjs.org/) framework to build our front-end. 361 | 362 | ## Creating Your AWS Amplify Application 363 | 364 | 1. Prerequisites: 365 | 366 | - [Node.js](https://nodejs.org/en/) v10.x or later 367 | - [npm](https://www.npmjs.com/) v5.x or later 368 | - [git](https://git-scm.com/) v2.14.1 or later 369 | 370 | 2. We first need to install and configure the AWS Amplify CLI. To do so, run the following command in your Terminal or shell prompt: 371 | ```Bash 372 | sudo npm install -g @aws-amplify/cli 373 | ``` 374 | 375 | 3. We now need to configure Amplify on our machine by providing our account information. Run the following command: 376 | ```Bash 377 | amplify configure 378 | ``` 379 | This command will open a window in your web browser and direct you to your AWS Console. If you are not currently logged in, log in to the AWS account that you would like to use for AWS Amplify. Once you are logged in to the console, go back to your shell prompt and hit Enter. ![AWS CLI Configure Setup](./amplify_pictures/AmplifyConfigureEnter.png) 380 | 381 | You will then be prompted to enter your region. You can find your region the same way you did in the previous section, by clicking on the tab in your AWS Console that displays a state or country name. ![AWS IoT Core How to Find Region](./iot_pictures/IoT%20Core%20How%20to%20Get%20Region.png) 382 | 383 | Next, you will be asked to provide a username for your Amplify user. This will add a user in AWS Identity Access Manager. It does not matter what you put here, just use a name that is descriptive and that you can remember (ex. amplify-iot). Once you hit Enter, another window on your browser will open. This window directs you to the IAM Add User page and automatically fills in the username you provided. Make sure "Programmatic access" is checked. You do not need to check "AWS Management Console access". Click "Next: Permissions" 384 | 385 | ![AWS Amplify IAM Add User](./amplify_pictures/AmplifyIAMAddUser.png) 386 | 387 | The next page shows the user's permissions. Make sure "Attach existing policies directly" is highlighted in the top selection. Also make sure that "AdministatorAccess" is checked. You may need to search for this policy and select it yourself. Click "Next: Tags" 388 | 389 | ![AWS Amplify IAM Policy](./amplify_pictures/AmplifyIAMPolicy.png) 390 | 391 | You do not need to add any tags, so click "Next: Review" 392 | 393 | ![AWS Amplify IAM Tags](./amplify_pictures/AmplifyIAMTags.png) 394 | 395 | Click "Create user". This should display a success message and allow you to see the user's Access Key ID and Secret access key. Make sure to download the csv file and keep it in a safe place, this is the only time you will be given these keys. After you have downloaded the csv files with your keys, hit "Close" 396 | 397 | ![AWS Amplify IAM Success](./amplify_pictures/AmplifyIAMSuccess.png) 398 | 399 | Back on your Terminal or shell prompt, hit Enter. You will be asked to enter your access key ID and secret access key. Open the csv file you downloaded and paste those keys into the terminal when prompted. 400 | 401 | ![AWS Amplify CLI Config](./amplify_pictures/AmplifyCLIConfig.png) 402 | 403 | You will then be prompted to provide a profile name, just use the default and hit Enter. You have now configured the Amplify CLI and added an IAM User with administrator access in your AWS account. 404 | 405 | 4. We will now create an Amplify application using the React framework. We will give it the name myamplifyapp but you can choose any name you would like (Note: Amplify application names cannot contain upper-case letters). Run the following command: 406 | ```Bash 407 | npx create-react-app myamplifyapp 408 | ``` 409 | 410 | 5. Run the following command to enter your application's root directory. 411 | ```Bash 412 | cd myamplifyapp 413 | ``` 414 | 415 | 6. Next, initialize your project using the following command. 416 | ```Bash 417 | amplify init 418 | ``` 419 | 420 | When prompted, enter all of the default settings. Enter "Y" when asked "Do you want to use an AWS profile?" and select "default" for the following prompt. 421 | 422 | Your project will then be initialized in the cloud. This process sets up an [AWS Cloud Formation](https://aws.amazon.com/cloudformation/) stack which includes IAM roles, S3 buckets, and other nested Cloud Formation stacks. This information can be seen in the AWS Console by searching for Cloud Formation. 423 | 424 | ![AWS Amplify CLI Init](./amplify_pictures/AmplifyInit.png) 425 | 426 | 7. To test the above steps, run the following command, which runs your application on your machine. Your web browser should appear and navigate to localhost:3000. You should see an empty React web page. 427 | ```Bash 428 | npm start 429 | ``` 430 | 431 | ![AWS Amplify Empty React Application](./amplify_pictures/AmplifyEmptyApp.png) 432 | 433 | Press Control->c in the command prompt to stop the application. 434 | 435 | ## Add Authentication To Your Application 436 | 437 | 1. In order for our application to interact with AWS IoT Core, we must first add authentication. We do this using the following command. 438 | ```Bash 439 | amplify add auth 440 | ``` 441 | 442 | Select default configuration, username for sign in, and no advanced settings. 443 | 444 | ![AWS Amplify Add Auth](./amplify_pictures/AmplifyAddAuth.png) 445 | 446 | 2. The previous step added an authentication back-end service in AWS Amplify. This allows us to use AWS Cognito in order to manage users on our website. Cognito uses User Pools and Identity Pools. First, we will setup a user pool for admins on the site. Run the following command to add a user pool. 447 | ```Bash 448 | amplify auth update 449 | ``` 450 | 451 | Choose "Create or update Cognito user pool groups" and when prompted, name your group "admin". Enter "N" when asked if you want to add another User Pool Group. You can add other groups to Cognito later throught the console. Since we only added one group, we do not need to do anything to sort them, just press Enter. 452 | 453 | ![AWS Amplify Add Cognito User Pool Group](./amplify_pictures/AmplifyAddUserPool.png) 454 | 455 | 3. To add the authentication service to your application in the cloud, run the following command: 456 | ```Bash 457 | amplify push 458 | ``` 459 | 460 | When asked if you want to continue, enter "Y". It may take a few minutes to push your changes. 461 | 462 | ![AWS Amplify Push](./amplify_pictures/AmplifyPush.png) 463 | 464 | If you would like to check to see these steps worked, log into the AWS Console and navigate to Cognito. Click "Manage User Pools" and then select "Users and Groups" on the left panel. Click "Groups" at the top and your admin group should be there. You won't have any users yet. 465 | 466 | ![AWS Amplify Cognito Admin Group](./amplify_pictures/AmplifyCognitoGroup.png) 467 | 468 | 4. Next, we need to install some dependencies for our application. Run the following commands. Note: you may need to run these with sudo if you have permission issues. 469 | ```Bash 470 | npm install aws-amplify 471 | npm install aws-amplify-react 472 | npm install react-bootstrap bootstrap 473 | ``` 474 | 475 | 5. In VS Code, open the root folder of your Amplify application. Open src/app.js. Replace the contents of that file with the following javascript: 476 | ```javascript 477 | import Amplify, { Auth, API } from 'aws-amplify'; 478 | import { withAuthenticator } from 'aws-amplify-react'; 479 | import React, { Component } from 'react'; 480 | import awsconfig from './aws-exports'; 481 | import '@aws-amplify/ui/dist/style.css'; 482 | import 'bootstrap/dist/css/bootstrap.min.css'; 483 | Amplify.configure(awsconfig); 484 | 485 | function App() { 486 | return ( 487 |
488 | Your app here 489 |
490 | ); 491 | } 492 | 493 | export default withAuthenticator(App, true); 494 | ``` 495 | 496 | 6. Run your application again with the following command in your terminal: 497 | ```Bash 498 | npm start 499 | ``` 500 | 501 | This will launch your application in a web browser and once it loads, you should be able to see the sign in page of your app. 502 | 503 | ![AWS Amplify Sign In Page](./amplify_pictures/AmplifySignInPage.png) 504 | 505 | 7. On your web application, click "Create account" to register a new user. Give the user a username and password that you will remember. The username we will use in this demo is amplifyDemoUser. Enter a valid email and phone number. You will need at least one of these for multi-factor authentication. Click "Create Account" 506 | 507 | ![AWS Amplify Sign In User](./amplify_pictures/AmplifySignInUser.png) 508 | 509 | An email will be sent to that email to verify your identity. Enter the confirmation code in the email into the box on your webpage. The webpage will ask you to sign in. Use the credentials you set in the this step. You should see a minimal application with a greeting, sign out button, and "Your app here" 510 | 511 | ![AWS Amplify Minimal Application](./amplify_pictures/AmplifyBlankApp.png) 512 | 513 | You should now be able to see that user if you go to Cognito in the AWS Console and click "Manage User Pools" and then "Users" 514 | 515 | ![AWS Amplify Cognito User](./amplify_pictures/AmplifyCognitoUser.png) 516 | 517 | ## Using the AWS Amplify PubSub Library to Communicate with AWS IoT Core 518 | 519 | Now that we have a basic application with user controls, we can use Amplify's PubSub library to publish and subscribe to AWS IoT topics. This will allow us to establish bidirectional communication between our Amplify application and our ESP32. 520 | 521 | 1. In order to use Amplify's PubSub library, we need to attach a policy to our Amazon Cognito Identity. First, we need to find our Cognito Identity ID. To find this, go to the AWS Console and find Cognito. Click "Manage Identity Pools". If this application is your only use of Cognito, there will be only one identity pool. If you have multiple identity pools, you must find the one that corresponds to your Amplify application. Click on the name of the identity from your Amplify application. 522 | 523 | ![AWS Amplify Cognito Identities](./amplify_pictures/AmplifyCognitoIdentities.png) 524 | 525 | 2. Click on "Identity Browser" in the left panel and there should be one identity in this view. Click on that identity. At the top, your identity ID is displayed. You will want this for the next step. 526 | 527 | ![AWS Amplify Cognito Identity ID](./amplify_pictures/AmplifyCognitoIdentityID.png) 528 | 529 | 3. We also need the name of the policy that we created during the IoT section. In this tutorial, we named our policy "ESP32Policy" but you may have named it something different. To see the name of your policy, go to AWS IoT Core in the AWS Console. Click on the "Secure" tab on the left panel and select "Policies". Your policy should be displayed here. 530 | 531 | ![AWS Amplify IOT Policy](./amplify_pictures/AmplifyIOTPolicy.png) 532 | 533 | 4. Next, use your Cognito Identity ID and your policy name in the following command in your terminal to attach our policy to our Cognito identity. 534 | ```Bash 535 | aws iot attach-principal-policy --policy-name '' --principal '' 536 | ``` 537 | 538 | ![AWS Amplify Attach Policy](./amplify_pictures/AmplifyAttachPolicy.png) 539 | 540 | 5. According to the Amplify Docs: 541 | >For your Cognito Authenticated Role to be able to interact with AWS IoT it may be necessary to update its permissions, if you haven’t done this before. 542 | 543 | To do this, log into the AWS Console and choose CloudFormation from the list of services. Locate the parent stack of your Amplify application, if this is your first time using Amplify, the parent stack will be the only Amplify stack that does not say "NESTED". You can also choose based on creation time. The description should say "Root stack for the Amplify AWS CloudFormation provider. 544 | 545 | ![AWS Amplify CloudFormation Parent Stack](./amplify_pictures/AmplifyParentStack.png) 546 | 547 | Select the "Resources" tab and find the "Auth Role" row. Click the link for "Physical ID" in that row. 548 | 549 | ![AWS Amplify CloudFormation AuthRole Physical ID](./amplify_pictures/AmplifyAuthRole.png) 550 | 551 | This will open IAM in a new tab. Click "Attach policies". Search "IoT" and select both "AWSIoTConfigAccess" and "AWSIoTDataAccess". Click "Attach policy" 552 | 553 | ![AWS Amplify AuthRole Permissions](./amplify_pictures/AmplifyAuthPerms.png) 554 | 555 | 6. Finally, return to VS Code. Replace the contents of src/App.js with the following code, making sure to replace the placeholders for your region and endpoint (you can also find this code in the amplify_code folder). To find your endpoint, go to AWS IoT Core from the AWS Console and click on "Settings" on the bottom of the left panel. Your IoT endpoint should be displayed. 556 | ```javascript 557 | import Amplify, { Auth, API } from 'aws-amplify'; 558 | import { withAuthenticator } from 'aws-amplify-react'; 559 | import React, { Component } from 'react'; 560 | import awsconfig from './aws-exports'; 561 | import '@aws-amplify/ui/dist/style.css'; 562 | import { PubSub } from 'aws-amplify'; 563 | import { AWSIoTProvider } from '@aws-amplify/pubsub/lib/Providers'; 564 | import 'bootstrap/dist/css/bootstrap.min.css'; 565 | import logo from './logo.svg'; 566 | Amplify.configure(awsconfig); 567 | 568 | var SUB_TOPIC = "esp32/pub"; 569 | var PUB_TOPIC = "esp32/sub"; 570 | 571 | // Apply plugin with configuration 572 | Amplify.addPluggable(new AWSIoTProvider({ 573 | aws_pubsub_region: '', 574 | aws_pubsub_endpoint: 'wss://xxxxxxxxxxxxx.iot..amazonaws.com/mqtt', 575 | })); 576 | 577 | async function ProcessMessage(payload) { 578 | console.log('Message received', payload); 579 | let topic=payload.value[Object.getOwnPropertySymbols(payload.value)[0]]; 580 | let time=payload.value.time; 581 | let sensor_a0=payload.value.sensor_a0; 582 | let scrollBox = document.getElementById('incomingMsg'); 583 | scrollBox.innerHTML += "NEW MESSAGE:

Topic: " + topic + "

Time: " + time + "

Sensor_a0: " + sensor_a0 + "

"; 584 | scrollBox.scrollTop = scrollBox.scrollHeight; 585 | } 586 | 587 | async function SendMessage() { 588 | let payload=document.getElementById('msg').value; 589 | document.getElementById('msg').value=''; 590 | console.log(payload); 591 | await PubSub.publish(PUB_TOPIC, { msg: payload }); 592 | document.getElementById('returnMsg').innerHTML = '

Message sent!

'; 593 | let sentMsgBox = document.getElementById('sentMsg'); 594 | sentMsgBox.innerHTML += payload + "

"; 595 | sentMsgBox.scrollTop = sentMsgBox.scrollHeight; 596 | } 597 | 598 | function App() { 599 | subscribe(); 600 | return ( 601 |
602 |
603 | logo 604 |

IoT Messaging

605 | Powered by AWS Cloud Computing 606 |
607 |
608 |
609 |

Publisher

610 |

The box below can be used to publish messages back to your devices by publishing to the topic {PUB_TOPIC}

611 |
Message:
612 | 613 |

614 | 615 |
616 |

617 |

Sent Messages:

618 |

Your sent messages will appear here

619 |
620 |
621 |



622 |
623 |

Subscriber

624 |

New messages from your device(s) that publish to the topic {SUB_TOPIC} will appear in the box below

625 |
626 |
627 |
628 |
629 | ); 630 | } 631 | 632 | function subscribe() { 633 | PubSub.subscribe(SUB_TOPIC).subscribe({ 634 | next: data => ProcessMessage(data), 635 | error: error => console.error(error), 636 | close: () => console.log('Done'), 637 | }); 638 | } 639 | 640 | export default withAuthenticator(App, true); 641 | ``` 642 | 643 | Restart your Amplify application by running the following command again. 644 | ```Bash 645 | npm start 646 | ``` 647 | 648 | Now go back to VS Code and open your Arduino application from Section I. Build the application and flash it to your device (you don't need to do this if this is already flashed onto your ESP32). Click the serial monitor button on the bottom bar of VS Code. This pulls up the Serial Monitor. You should see that your ESP32 has again connected to Wifi and AWS IoT. Your device is now publishing messages onto the topic "esp32/pub". 649 | 650 | ![AWS Amplify Device Connected](./amplify_pictures/AmplifyDeviceConnected.png) 651 | 652 | Navigate to your Amplify application in your web browser (should have opened from the previous command but can also be reached at localhost:3000). On the right, you should see the messages coming in from your ESP32. Each message should show the topic, time, and sensor value. Since no sensor is connected, this value will mostly likely remain constant. 653 | 654 | ![AWS Amplify Working Message Subscriber](./amplify_pictures/AmplifyIncomingMsg.png) 655 | 656 | You can also send messages from your Amplify application back to the ESP32. To do so, simply type a message into the input box and click "Send Message". You will see a success message. 657 | 658 | ![AWS Amplify Sending Message](./amplify_pictures/AmplifySendMsg.png) 659 | 660 | ![AWS Amplify Sent Message](./amplify_pictures/AmplifySentMsg.png) 661 | 662 | Back on the Serial Monitor for the ESP32 in VS Code, you can see that your message has been successfully delivered. 663 | 664 | ![AWS Amplify Message Received](./amplify_pictures/AmplifyMsgReceived.png) 665 | 666 | ## Deploying Your Web Application 667 | 668 | Currently, your Amplify application is currently hosted on your local machine. AWS offers hosting for your application. Note that a free tier is available but can be exceeded. Amplify pricing is based on build minutes and size of content delivered. If you would like your application to be hosted, use the following command from the root directory of your Amplify application. 669 | ```Bash 670 | amplify add hosting 671 | ``` 672 | 673 | You can either host your application on the Amplify Console or with CouldFront and S3. For this tutorial, we will use the Amplify Console. We will also use manual deployment. 674 | 675 | ![AWS Amplify Add Hosting](./amplify_pictures/AmplifyAddHosting.png) 676 | 677 | To publish your app, run the command: 678 | ```Bash 679 | amplify publish 680 | ``` 681 | 682 | When asked if you want to continue, enter "Y" 683 | 684 | ![AWS Amplify Publish](./amplify_pictures/AmplifyPublish.png) 685 | 686 | Once your application is finished publishing, you can go to your site using the URL provided at the end of the command output. 687 | 688 | ![AWS Amplify URL](./amplify_pictures/AmplifyURL.png) 689 | 690 | You now have a web application in the cloud that can communicate bidirectionally with your ESP32. This idea can be scaled into any type of IoT application. The possibilities are endless! Next steps include but are not limited to: 691 | -Connecting sensors to receive real time data from your ESP32 on your web application 692 | -Interpreting the return messages on the ESP32 to produce some desired behavior 693 | -Including more IoT devices that publish to the same topic 694 | -Creating your own front end to show trends over time of your IoT data 695 | 696 | ## Video Guide 697 | To see a step-by-step video guide, see this [video](https://amazon.awsapps.com/workdocs/index.html#/document/819bd727b0753e2c342dafda6d2796e5e6c541140644cdc9c6a92bb162f45a39). 698 | 699 | ## Security 700 | 701 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 702 | 703 | ## License 704 | 705 | This library is licensed under the MIT-0 License. See the LICENSE file. 706 | 707 | -------------------------------------------------------------------------------- /amplify_code/amplify/#current-cloud-backend/amplify-meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "providers": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplify-myamplifyapp-dev-143204-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::109499523128:role/amplify-myamplifyapp-dev-143204-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::109499523128:role/amplify-myamplifyapp-dev-143204-authRole", 7 | "Region": "us-west-2", 8 | "DeploymentBucketName": "amplify-myamplifyapp-dev-143204-deployment", 9 | "UnauthRoleName": "amplify-myamplifyapp-dev-143204-unauthRole", 10 | "StackName": "amplify-myamplifyapp-dev-143204", 11 | "StackId": "arn:aws:cloudformation:us-west-2:109499523128:stack/amplify-myamplifyapp-dev-143204/4eb1b5e0-c099-11ea-9286-02b0d23de91c", 12 | "AmplifyAppId": "d2o2lsbvokqla0" 13 | } 14 | }, 15 | "auth": { 16 | "myamplifyapp84642f50": { 17 | "service": "Cognito", 18 | "providerPlugin": "awscloudformation", 19 | "dependsOn": [], 20 | "customAuth": false, 21 | "lastPushTimeStamp": "2020-07-07T22:09:50.963Z", 22 | "providerMetadata": { 23 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-myamplifyapp-dev-143204-deployment/amplify-cfn-templates/auth/myamplifyapp84642f50-cloudformation-template.yml", 24 | "logicalId": "authmyamplifyapp84642f50" 25 | }, 26 | "output": { 27 | "AppClientSecret": "ms5pq7dpop1ee3fgt7vfppu0d1pgnlpta3d1p0821qfdhe9397k", 28 | "UserPoolId": "us-west-2_FHcBMjfC6", 29 | "AppClientIDWeb": "lc2la0msvfu0jjc474b77c1nj", 30 | "AppClientID": "592qgm3hdmj7j8h3nob6fvl483", 31 | "IdentityPoolId": "us-west-2:b4b257fb-fa4f-45bd-9ae0-bf0743af5da0", 32 | "IdentityPoolName": "myamplifyapp84642f50_identitypool_84642f50__dev", 33 | "UserPoolName": "myamplifyapp84642f50_userpool_84642f50" 34 | }, 35 | "lastPushDirHash": "27SWqEu10DOUIusZ7DjFwt832Us=" 36 | }, 37 | "userPoolGroups": { 38 | "service": "Cognito-UserPool-Groups", 39 | "providerPlugin": "awscloudformation", 40 | "dependsOn": [ 41 | { 42 | "category": "auth", 43 | "resourceName": "myamplifyapp84642f50", 44 | "attributes": [ 45 | "UserPoolId", 46 | "AppClientIDWeb", 47 | "AppClientID", 48 | "IdentityPoolId" 49 | ] 50 | } 51 | ], 52 | "lastPushTimeStamp": "2020-07-07T22:09:50.963Z", 53 | "providerMetadata": { 54 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-myamplifyapp-dev-143204-deployment/amplify-cfn-templates/auth/template.json", 55 | "logicalId": "authuserPoolGroups" 56 | }, 57 | "output": { 58 | "adminGroupRole": "arn:aws:iam::109499523128:role/us-west-2_FHcBMjfC6-adminGroupRole" 59 | }, 60 | "lastPushDirHash": "ul0e4kVQ/f1WbtKk0LeBANCb4ho=" 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /amplify_code/amplify/#current-cloud-backend/auth/myamplifyapp84642f50/myamplifyapp84642f50-cloudformation-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | 3 | Parameters: 4 | env: 5 | Type: String 6 | authRoleArn: 7 | Type: String 8 | unauthRoleArn: 9 | Type: String 10 | 11 | 12 | 13 | 14 | identityPoolName: 15 | Type: String 16 | 17 | allowUnauthenticatedIdentities: 18 | Type: String 19 | 20 | resourceNameTruncated: 21 | Type: String 22 | 23 | userPoolName: 24 | Type: String 25 | 26 | autoVerifiedAttributes: 27 | Type: CommaDelimitedList 28 | 29 | mfaConfiguration: 30 | Type: String 31 | 32 | mfaTypes: 33 | Type: CommaDelimitedList 34 | 35 | smsAuthenticationMessage: 36 | Type: String 37 | 38 | smsVerificationMessage: 39 | Type: String 40 | 41 | emailVerificationSubject: 42 | Type: String 43 | 44 | emailVerificationMessage: 45 | Type: String 46 | 47 | defaultPasswordPolicy: 48 | Type: String 49 | 50 | passwordPolicyMinLength: 51 | Type: Number 52 | 53 | passwordPolicyCharacters: 54 | Type: CommaDelimitedList 55 | 56 | requiredAttributes: 57 | Type: CommaDelimitedList 58 | 59 | userpoolClientGenerateSecret: 60 | Type: String 61 | 62 | userpoolClientRefreshTokenValidity: 63 | Type: Number 64 | 65 | userpoolClientWriteAttributes: 66 | Type: CommaDelimitedList 67 | 68 | userpoolClientReadAttributes: 69 | Type: CommaDelimitedList 70 | 71 | userpoolClientLambdaRole: 72 | Type: String 73 | 74 | userpoolClientSetAttributes: 75 | Type: String 76 | 77 | sharedId: 78 | Type: String 79 | 80 | resourceName: 81 | Type: String 82 | 83 | authSelections: 84 | Type: String 85 | 86 | useDefault: 87 | Type: String 88 | 89 | userPoolGroupList: 90 | Type: CommaDelimitedList 91 | 92 | dependsOn: 93 | Type: CommaDelimitedList 94 | 95 | Conditions: 96 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 97 | 98 | Resources: 99 | 100 | 101 | # BEGIN SNS ROLE RESOURCE 102 | SNSRole: 103 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 104 | Type: AWS::IAM::Role 105 | Properties: 106 | RoleName: !If [ShouldNotCreateEnvResources, 'myampl84642f50_sns-role', !Join ['',[ 'sns', '84642f50', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 107 | AssumeRolePolicyDocument: 108 | Version: "2012-10-17" 109 | Statement: 110 | - Sid: "" 111 | Effect: "Allow" 112 | Principal: 113 | Service: "cognito-idp.amazonaws.com" 114 | Action: 115 | - "sts:AssumeRole" 116 | Condition: 117 | StringEquals: 118 | sts:ExternalId: myampl84642f50_role_external_id 119 | Policies: 120 | - 121 | PolicyName: myampl84642f50-sns-policy 122 | PolicyDocument: 123 | Version: "2012-10-17" 124 | Statement: 125 | - 126 | Effect: "Allow" 127 | Action: 128 | - "sns:Publish" 129 | Resource: "*" 130 | # BEGIN USER POOL RESOURCES 131 | UserPool: 132 | # Created upon user selection 133 | # Depends on SNS Role for Arn if MFA is enabled 134 | Type: AWS::Cognito::UserPool 135 | UpdateReplacePolicy: Retain 136 | Properties: 137 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 138 | 139 | Schema: 140 | 141 | - 142 | Name: email 143 | Required: true 144 | Mutable: true 145 | 146 | 147 | 148 | 149 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 150 | 151 | 152 | EmailVerificationMessage: !Ref emailVerificationMessage 153 | EmailVerificationSubject: !Ref emailVerificationSubject 154 | 155 | Policies: 156 | PasswordPolicy: 157 | MinimumLength: !Ref passwordPolicyMinLength 158 | RequireLowercase: false 159 | RequireNumbers: false 160 | RequireSymbols: false 161 | RequireUppercase: false 162 | 163 | MfaConfiguration: !Ref mfaConfiguration 164 | SmsVerificationMessage: !Ref smsVerificationMessage 165 | SmsConfiguration: 166 | SnsCallerArn: !GetAtt SNSRole.Arn 167 | ExternalId: myampl84642f50_role_external_id 168 | 169 | 170 | UserPoolClientWeb: 171 | # Created provide application access to user pool 172 | # Depends on UserPool for ID reference 173 | Type: "AWS::Cognito::UserPoolClient" 174 | Properties: 175 | ClientName: myampl84642f50_app_clientWeb 176 | 177 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 178 | UserPoolId: !Ref UserPool 179 | DependsOn: UserPool 180 | UserPoolClient: 181 | # Created provide application access to user pool 182 | # Depends on UserPool for ID reference 183 | Type: "AWS::Cognito::UserPoolClient" 184 | Properties: 185 | ClientName: myampl84642f50_app_client 186 | 187 | GenerateSecret: !Ref userpoolClientGenerateSecret 188 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 189 | UserPoolId: !Ref UserPool 190 | DependsOn: UserPool 191 | # BEGIN USER POOL LAMBDA RESOURCES 192 | UserPoolClientRole: 193 | # Created to execute Lambda which gets userpool app client config values 194 | Type: 'AWS::IAM::Role' 195 | Properties: 196 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', '84642f50', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 197 | AssumeRolePolicyDocument: 198 | Version: '2012-10-17' 199 | Statement: 200 | - Effect: Allow 201 | Principal: 202 | Service: 203 | - lambda.amazonaws.com 204 | Action: 205 | - 'sts:AssumeRole' 206 | DependsOn: UserPoolClient 207 | UserPoolClientLambda: 208 | # Lambda which gets userpool app client config values 209 | # Depends on UserPool for id 210 | # Depends on UserPoolClientRole for role ARN 211 | Type: 'AWS::Lambda::Function' 212 | Properties: 213 | Code: 214 | ZipFile: !Join 215 | - |+ 216 | - - 'const response = require(''cfn-response'');' 217 | - 'const aws = require(''aws-sdk'');' 218 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 219 | - 'exports.handler = (event, context, callback) => {' 220 | - ' if (event.RequestType == ''Delete'') { ' 221 | - ' response.send(event, context, response.SUCCESS, {})' 222 | - ' }' 223 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 224 | - ' const params = {' 225 | - ' ClientId: event.ResourceProperties.clientId,' 226 | - ' UserPoolId: event.ResourceProperties.userpoolId' 227 | - ' };' 228 | - ' identity.describeUserPoolClient(params).promise()' 229 | - ' .then((res) => {' 230 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 231 | - ' })' 232 | - ' .catch((err) => {' 233 | - ' response.send(event, context, response.FAILED, {err});' 234 | - ' });' 235 | - ' }' 236 | - '};' 237 | Handler: index.handler 238 | Runtime: nodejs14.x 239 | Timeout: '300' 240 | Role: !GetAtt 241 | - UserPoolClientRole 242 | - Arn 243 | DependsOn: UserPoolClientRole 244 | UserPoolClientLambdaPolicy: 245 | # Sets userpool policy for the role that executes the Userpool Client Lambda 246 | # Depends on UserPool for Arn 247 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 248 | Type: 'AWS::IAM::Policy' 249 | Properties: 250 | PolicyName: myampl84642f50_userpoolclient_lambda_iam_policy 251 | Roles: 252 | - !Ref UserPoolClientRole 253 | PolicyDocument: 254 | Version: '2012-10-17' 255 | Statement: 256 | - Effect: Allow 257 | Action: 258 | - 'cognito-idp:DescribeUserPoolClient' 259 | Resource: !GetAtt UserPool.Arn 260 | DependsOn: UserPoolClientLambda 261 | UserPoolClientLogPolicy: 262 | # Sets log policy for the role that executes the Userpool Client Lambda 263 | # Depends on UserPool for Arn 264 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 265 | Type: 'AWS::IAM::Policy' 266 | Properties: 267 | PolicyName: myampl84642f50_userpoolclient_lambda_log_policy 268 | Roles: 269 | - !Ref UserPoolClientRole 270 | PolicyDocument: 271 | Version: 2012-10-17 272 | Statement: 273 | - Effect: Allow 274 | Action: 275 | - 'logs:CreateLogGroup' 276 | - 'logs:CreateLogStream' 277 | - 'logs:PutLogEvents' 278 | Resource: !Sub 279 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 280 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 281 | DependsOn: UserPoolClientLambdaPolicy 282 | UserPoolClientInputs: 283 | # Values passed to Userpool client Lambda 284 | # Depends on UserPool for Id 285 | # Depends on UserPoolClient for Id 286 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 287 | Type: 'Custom::LambdaCallout' 288 | Properties: 289 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 290 | clientId: !Ref UserPoolClient 291 | userpoolId: !Ref UserPool 292 | DependsOn: UserPoolClientLogPolicy 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | # BEGIN IDENTITY POOL RESOURCES 301 | 302 | 303 | IdentityPool: 304 | # Always created 305 | Type: AWS::Cognito::IdentityPool 306 | Properties: 307 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'myamplifyapp84642f50_identitypool_84642f50', !Join ['',['myamplifyapp84642f50_identitypool_84642f50', '__', !Ref env]]] 308 | 309 | CognitoIdentityProviders: 310 | - ClientId: !Ref UserPoolClient 311 | ProviderName: !Sub 312 | - cognito-idp.${region}.amazonaws.com/${client} 313 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 314 | - ClientId: !Ref UserPoolClientWeb 315 | ProviderName: !Sub 316 | - cognito-idp.${region}.amazonaws.com/${client} 317 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 318 | 319 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 320 | 321 | 322 | DependsOn: UserPoolClientInputs 323 | 324 | 325 | IdentityPoolRoleMap: 326 | # Created to map Auth and Unauth roles to the identity pool 327 | # Depends on Identity Pool for ID ref 328 | Type: AWS::Cognito::IdentityPoolRoleAttachment 329 | Properties: 330 | IdentityPoolId: !Ref IdentityPool 331 | Roles: 332 | unauthenticated: !Ref unauthRoleArn 333 | authenticated: !Ref authRoleArn 334 | DependsOn: IdentityPool 335 | 336 | 337 | Outputs : 338 | 339 | IdentityPoolId: 340 | Value: !Ref 'IdentityPool' 341 | Description: Id for the identity pool 342 | IdentityPoolName: 343 | Value: !GetAtt IdentityPool.Name 344 | 345 | 346 | 347 | 348 | UserPoolId: 349 | Value: !Ref 'UserPool' 350 | Description: Id for the user pool 351 | UserPoolName: 352 | Value: !Ref userPoolName 353 | AppClientIDWeb: 354 | Value: !Ref 'UserPoolClientWeb' 355 | Description: The user pool app client id for web 356 | AppClientID: 357 | Value: !Ref 'UserPoolClient' 358 | Description: The user pool app client id 359 | AppClientSecret: 360 | Value: !GetAtt UserPoolClientInputs.appSecret 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | -------------------------------------------------------------------------------- /amplify_code/amplify/#current-cloud-backend/auth/myamplifyapp84642f50/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "myamplifyapp84642f50_identitypool_84642f50", 3 | "allowUnauthenticatedIdentities": false, 4 | "resourceNameTruncated": "myampl84642f50", 5 | "userPoolName": "myamplifyapp84642f50_userpool_84642f50", 6 | "autoVerifiedAttributes": [ 7 | "email" 8 | ], 9 | "mfaConfiguration": "OFF", 10 | "mfaTypes": [ 11 | "SMS Text Message" 12 | ], 13 | "smsAuthenticationMessage": "Your authentication code is {####}", 14 | "smsVerificationMessage": "Your verification code is {####}", 15 | "emailVerificationSubject": "Your verification code", 16 | "emailVerificationMessage": "Your verification code is {####}", 17 | "defaultPasswordPolicy": false, 18 | "passwordPolicyMinLength": 8, 19 | "passwordPolicyCharacters": [], 20 | "requiredAttributes": [ 21 | "email" 22 | ], 23 | "userpoolClientGenerateSecret": true, 24 | "userpoolClientRefreshTokenValidity": 30, 25 | "userpoolClientWriteAttributes": [ 26 | "email" 27 | ], 28 | "userpoolClientReadAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientLambdaRole": "myampl84642f50_userpoolclient_lambda_role", 32 | "userpoolClientSetAttributes": false, 33 | "sharedId": "84642f50", 34 | "resourceName": "myamplifyapp84642f50", 35 | "authSelections": "identityPoolAndUserPool", 36 | "authRoleArn": { 37 | "Fn::GetAtt": [ 38 | "AuthRole", 39 | "Arn" 40 | ] 41 | }, 42 | "unauthRoleArn": { 43 | "Fn::GetAtt": [ 44 | "UnauthRole", 45 | "Arn" 46 | ] 47 | }, 48 | "useDefault": "default", 49 | "userPoolGroupList": [], 50 | "dependsOn": [] 51 | } -------------------------------------------------------------------------------- /amplify_code/amplify/#current-cloud-backend/auth/userPoolGroups/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "AuthRoleArn": { 3 | "Fn::GetAtt": [ 4 | "AuthRole", 5 | "Arn" 6 | ] 7 | }, 8 | "UnauthRoleArn": { 9 | "Fn::GetAtt": [ 10 | "UnauthRole", 11 | "Arn" 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /amplify_code/amplify/#current-cloud-backend/auth/userPoolGroups/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Parameters": { 4 | "authmyamplifyapp84642f50UserPoolId": { 5 | "Type": "String", 6 | "Default": "authmyamplifyapp84642f50UserPoolId" 7 | }, 8 | 9 | "authmyamplifyapp84642f50IdentityPoolId": { 10 | "Type": "String", 11 | "Default": "authmyamplifyapp84642f50IdentityPoolId" 12 | }, 13 | 14 | "authmyamplifyapp84642f50AppClientID": { 15 | "Type": "String", 16 | "Default": "authmyamplifyapp84642f50AppClientID" 17 | }, 18 | "authmyamplifyapp84642f50AppClientIDWeb": { 19 | "Type": "String", 20 | "Default": "authmyamplifyapp84642f50AppClientIDWeb" 21 | }, 22 | "AuthRoleArn": { 23 | "Type": "String" 24 | }, 25 | "UnauthRoleArn": { 26 | "Type": "String" 27 | }, 28 | "env": { 29 | "Type": "String" 30 | } 31 | }, 32 | "Conditions": { 33 | "ShouldNotCreateEnvResources": { 34 | "Fn::Equals": [ 35 | { 36 | "Ref": "env" 37 | }, 38 | "NONE" 39 | ] 40 | } 41 | }, 42 | "Resources": { 43 | 44 | "adminGroup": { 45 | "Type" : "AWS::Cognito::UserPoolGroup", 46 | "Properties" : { 47 | "GroupName" : "admin", 48 | "Precedence" : 1, 49 | 50 | "RoleArn" : { 51 | "Fn::GetAtt": [ 52 | "adminGroupRole", 53 | "Arn" 54 | ] 55 | }, 56 | 57 | "UserPoolId" : { 58 | "Ref": "authmyamplifyapp84642f50UserPoolId" 59 | } 60 | } 61 | }, 62 | 63 | "adminGroupRole": { 64 | "Type": "AWS::IAM::Role", 65 | "Properties": { 66 | "RoleName":{ 67 | "Fn::Join": [ 68 | "", 69 | [ 70 | { 71 | "Ref": "authmyamplifyapp84642f50UserPoolId" 72 | }, 73 | "-adminGroupRole" 74 | ] 75 | ] 76 | }, 77 | "AssumeRolePolicyDocument": { 78 | "Version": "2012-10-17", 79 | "Statement": [ 80 | { 81 | "Sid": "", 82 | "Effect": "Allow", 83 | "Principal": { 84 | "Federated": "cognito-identity.amazonaws.com" 85 | }, 86 | "Action": "sts:AssumeRoleWithWebIdentity", 87 | "Condition": { 88 | "StringEquals": {"cognito-identity.amazonaws.com:aud": {"Ref":"authmyamplifyapp84642f50IdentityPoolId"}}, 89 | "ForAnyValue:StringLike": {"cognito-identity.amazonaws.com:amr": "authenticated"} 90 | } 91 | } 92 | ] 93 | } 94 | } 95 | }, 96 | 97 | 98 | 99 | "LambdaExecutionRole": { 100 | "Type": "AWS::IAM::Role", 101 | "Properties": { 102 | "RoleName": { 103 | "Fn::If": [ 104 | "ShouldNotCreateEnvResources", 105 | { 106 | 107 | }, 108 | { 109 | 110 | "Fn::Join": [ 111 | "", 112 | [ 113 | 114 | "myamplifyapp84642f50", 115 | "-ExecutionRole-", 116 | { 117 | "Ref": "env" 118 | } 119 | ] 120 | ] 121 | } 122 | ] 123 | }, 124 | "AssumeRolePolicyDocument": { 125 | "Version": "2012-10-17", 126 | "Statement": [ 127 | { 128 | "Effect": "Allow", 129 | "Principal": { 130 | "Service": [ 131 | "lambda.amazonaws.com" 132 | ] 133 | }, 134 | "Action": [ 135 | "sts:AssumeRole" 136 | ] 137 | } 138 | ] 139 | }, 140 | "Policies": [ 141 | { 142 | "PolicyName": "UserGroupLogPolicy", 143 | "PolicyDocument": { 144 | "Version": "2012-10-17", 145 | "Statement": [ 146 | { 147 | "Effect": "Allow", 148 | "Action": [ 149 | "logs:CreateLogGroup", 150 | "logs:CreateLogStream", 151 | "logs:PutLogEvents" 152 | ], 153 | "Resource": "arn:aws:logs:*:*:*" 154 | } 155 | ] 156 | } 157 | }, 158 | { 159 | "PolicyName": "UserGroupExecutionPolicy", 160 | "PolicyDocument": { 161 | "Version": "2012-10-17", 162 | "Statement": [ 163 | { 164 | "Effect": "Allow", 165 | "Action": [ 166 | "cognito-identity:SetIdentityPoolRoles", 167 | "cognito-identity:ListIdentityPools", 168 | "cognito-identity:describeIdentityPool" 169 | 170 | ], 171 | "Resource": "*" 172 | } 173 | ] 174 | } 175 | }, 176 | { 177 | "PolicyName": "UserGroupPassRolePolicy", 178 | "PolicyDocument": { 179 | "Version": "2012-10-17", 180 | "Statement": [ 181 | { 182 | "Effect": "Allow", 183 | "Action": [ 184 | "iam:PassRole" 185 | ], 186 | "Resource": "*" 187 | } 188 | ] 189 | } 190 | } 191 | ] 192 | } 193 | }, 194 | "RoleMapFunction": { 195 | "Type": "AWS::Lambda::Function", 196 | "DependsOn": ["LambdaExecutionRole"], 197 | "Properties": { 198 | "Code": { 199 | "ZipFile": { 200 | "Fn::Join": [ 201 | "\n", 202 | [ 203 | "const response = require('cfn-response');", 204 | "const AWS = require('aws-sdk');", 205 | "exports.handler = (event, context) => {", 206 | "if (event.RequestType == 'Delete') {", 207 | " response.send(event, context, response.SUCCESS, {message: 'Request type delete'})", 208 | "};", 209 | "if (event.RequestType == 'Create' || event.RequestType == 'Update') {", 210 | " let { identityPoolId, appClientID, appClientIDWeb, userPoolId, region } = event.ResourceProperties;", 211 | " try {", 212 | " const cognitoidentity = new AWS.CognitoIdentity();", 213 | " let params = {", 214 | " IdentityPoolId: identityPoolId,", 215 | " Roles: {", 216 | " 'authenticated': event.ResourceProperties.AuthRoleArn,", 217 | " 'unauthenticated': event.ResourceProperties.UnauthRoleArn,", 218 | " },", 219 | " RoleMappings: {}", 220 | " };", 221 | " if (appClientIDWeb) {", 222 | " params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientIDWeb}`] = {", 223 | " Type: 'Token',", 224 | " AmbiguousRoleResolution: 'AuthenticatedRole',", 225 | " }", 226 | " }", 227 | " if (appClientID) {", 228 | " params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientID}`] = {", 229 | " Type: 'Token',", 230 | " AmbiguousRoleResolution: 'AuthenticatedRole',", 231 | " }", 232 | " }", 233 | " cognitoidentity.setIdentityPoolRoles(params).promise();", 234 | " response.send(event, context, response.SUCCESS, {message: 'Successfully updated identity pool.'})", 235 | " } catch(err) {", 236 | 237 | " response.send(event, context, response.FAILED, {message: 'Error updating identity pool'});", 238 | " }", 239 | " };", 240 | "};" 241 | 242 | ] 243 | ] 244 | } 245 | }, 246 | "Handler": "index.handler", 247 | "Runtime": "nodejs14.x", 248 | "Timeout": "300", 249 | "Role": { 250 | "Fn::GetAtt": [ 251 | "LambdaExecutionRole", 252 | "Arn" 253 | ] 254 | } 255 | } 256 | }, 257 | "RoleMapFunctionInput": { 258 | "Type": "Custom::LambdaCallout", 259 | "Properties": { 260 | "ServiceToken": { 261 | "Fn::GetAtt": [ 262 | "RoleMapFunction", 263 | "Arn" 264 | ] 265 | }, 266 | "AuthRoleArn": { 267 | "Ref": "AuthRoleArn" 268 | }, 269 | "UnauthRoleArn": { 270 | "Ref": "UnauthRoleArn" 271 | }, 272 | "identityPoolId": { 273 | "Ref": "authmyamplifyapp84642f50IdentityPoolId" 274 | }, 275 | "userPoolId": { 276 | "Ref": "authmyamplifyapp84642f50UserPoolId" 277 | }, 278 | "appClientIDWeb": { 279 | "Ref": "authmyamplifyapp84642f50AppClientIDWeb" 280 | }, 281 | "appClientID": { 282 | "Ref": "authmyamplifyapp84642f50AppClientID" 283 | }, 284 | "region": { 285 | "Ref": "AWS::Region" 286 | }, 287 | "env": { 288 | "Ref": "env" 289 | } 290 | }, 291 | "DependsOn": ["RoleMapFunction"] 292 | } 293 | 294 | }, 295 | 296 | "Outputs": { 297 | 298 | "adminGroupRole": { 299 | "Value": { 300 | "Fn::GetAtt": [ 301 | "adminGroupRole", 302 | "Arn" 303 | ] 304 | } 305 | 306 | } 307 | 308 | 309 | } 310 | 311 | } 312 | -------------------------------------------------------------------------------- /amplify_code/amplify/#current-cloud-backend/auth/userPoolGroups/user-pool-group-precedence.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "groupName": "admin", 4 | "precedence": 1 5 | } 6 | ] -------------------------------------------------------------------------------- /amplify_code/amplify/#current-cloud-backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "myamplifyapp84642f50": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [], 7 | "customAuth": false 8 | }, 9 | "userPoolGroups": { 10 | "service": "Cognito-UserPool-Groups", 11 | "providerPlugin": "awscloudformation", 12 | "dependsOn": [ 13 | { 14 | "category": "auth", 15 | "resourceName": "myamplifyapp84642f50", 16 | "attributes": [ 17 | "UserPoolId", 18 | "AppClientIDWeb", 19 | "AppClientID", 20 | "IdentityPoolId" 21 | ] 22 | } 23 | ] 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /amplify_code/amplify/backend/amplify-meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "providers": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplify-myamplifyapp-dev-143204-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::109499523128:role/amplify-myamplifyapp-dev-143204-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::109499523128:role/amplify-myamplifyapp-dev-143204-authRole", 7 | "Region": "us-west-2", 8 | "DeploymentBucketName": "amplify-myamplifyapp-dev-143204-deployment", 9 | "UnauthRoleName": "amplify-myamplifyapp-dev-143204-unauthRole", 10 | "StackName": "amplify-myamplifyapp-dev-143204", 11 | "StackId": "arn:aws:cloudformation:us-west-2:109499523128:stack/amplify-myamplifyapp-dev-143204/4eb1b5e0-c099-11ea-9286-02b0d23de91c", 12 | "AmplifyAppId": "d2o2lsbvokqla0" 13 | } 14 | }, 15 | "auth": { 16 | "myamplifyapp84642f50": { 17 | "service": "Cognito", 18 | "providerPlugin": "awscloudformation", 19 | "dependsOn": [], 20 | "customAuth": false, 21 | "lastPushTimeStamp": "2020-07-07T22:09:50.963Z", 22 | "providerMetadata": { 23 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-myamplifyapp-dev-143204-deployment/amplify-cfn-templates/auth/myamplifyapp84642f50-cloudformation-template.yml", 24 | "logicalId": "authmyamplifyapp84642f50" 25 | }, 26 | "output": { 27 | "AppClientSecret": "ms5pq7dpop1ee3fgt7vfppu0d1pgnlpta3d1p0821qfdhe9397k", 28 | "UserPoolId": "us-west-2_FHcBMjfC6", 29 | "AppClientIDWeb": "lc2la0msvfu0jjc474b77c1nj", 30 | "AppClientID": "592qgm3hdmj7j8h3nob6fvl483", 31 | "IdentityPoolId": "us-west-2:b4b257fb-fa4f-45bd-9ae0-bf0743af5da0", 32 | "IdentityPoolName": "myamplifyapp84642f50_identitypool_84642f50__dev", 33 | "UserPoolName": "myamplifyapp84642f50_userpool_84642f50" 34 | }, 35 | "lastPushDirHash": "27SWqEu10DOUIusZ7DjFwt832Us=" 36 | }, 37 | "userPoolGroups": { 38 | "service": "Cognito-UserPool-Groups", 39 | "providerPlugin": "awscloudformation", 40 | "dependsOn": [ 41 | { 42 | "category": "auth", 43 | "resourceName": "myamplifyapp84642f50", 44 | "attributes": [ 45 | "UserPoolId", 46 | "AppClientIDWeb", 47 | "AppClientID", 48 | "IdentityPoolId" 49 | ] 50 | } 51 | ], 52 | "lastPushTimeStamp": "2020-07-07T22:09:50.963Z", 53 | "providerMetadata": { 54 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-myamplifyapp-dev-143204-deployment/amplify-cfn-templates/auth/template.json", 55 | "logicalId": "authuserPoolGroups" 56 | }, 57 | "output": { 58 | "adminGroupRole": "arn:aws:iam::109499523128:role/us-west-2_FHcBMjfC6-adminGroupRole" 59 | }, 60 | "lastPushDirHash": "ul0e4kVQ/f1WbtKk0LeBANCb4ho=" 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /amplify_code/amplify/backend/auth/myamplifyapp84642f50/myamplifyapp84642f50-cloudformation-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | 3 | Parameters: 4 | env: 5 | Type: String 6 | authRoleArn: 7 | Type: String 8 | unauthRoleArn: 9 | Type: String 10 | 11 | 12 | 13 | 14 | identityPoolName: 15 | Type: String 16 | 17 | allowUnauthenticatedIdentities: 18 | Type: String 19 | 20 | resourceNameTruncated: 21 | Type: String 22 | 23 | userPoolName: 24 | Type: String 25 | 26 | autoVerifiedAttributes: 27 | Type: CommaDelimitedList 28 | 29 | mfaConfiguration: 30 | Type: String 31 | 32 | mfaTypes: 33 | Type: CommaDelimitedList 34 | 35 | smsAuthenticationMessage: 36 | Type: String 37 | 38 | smsVerificationMessage: 39 | Type: String 40 | 41 | emailVerificationSubject: 42 | Type: String 43 | 44 | emailVerificationMessage: 45 | Type: String 46 | 47 | defaultPasswordPolicy: 48 | Type: String 49 | 50 | passwordPolicyMinLength: 51 | Type: Number 52 | 53 | passwordPolicyCharacters: 54 | Type: CommaDelimitedList 55 | 56 | requiredAttributes: 57 | Type: CommaDelimitedList 58 | 59 | userpoolClientGenerateSecret: 60 | Type: String 61 | 62 | userpoolClientRefreshTokenValidity: 63 | Type: Number 64 | 65 | userpoolClientWriteAttributes: 66 | Type: CommaDelimitedList 67 | 68 | userpoolClientReadAttributes: 69 | Type: CommaDelimitedList 70 | 71 | userpoolClientLambdaRole: 72 | Type: String 73 | 74 | userpoolClientSetAttributes: 75 | Type: String 76 | 77 | sharedId: 78 | Type: String 79 | 80 | resourceName: 81 | Type: String 82 | 83 | authSelections: 84 | Type: String 85 | 86 | useDefault: 87 | Type: String 88 | 89 | userPoolGroupList: 90 | Type: CommaDelimitedList 91 | 92 | dependsOn: 93 | Type: CommaDelimitedList 94 | 95 | Conditions: 96 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 97 | 98 | Resources: 99 | 100 | 101 | # BEGIN SNS ROLE RESOURCE 102 | SNSRole: 103 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 104 | Type: AWS::IAM::Role 105 | Properties: 106 | RoleName: !If [ShouldNotCreateEnvResources, 'myampl84642f50_sns-role', !Join ['',[ 'sns', '84642f50', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 107 | AssumeRolePolicyDocument: 108 | Version: "2012-10-17" 109 | Statement: 110 | - Sid: "" 111 | Effect: "Allow" 112 | Principal: 113 | Service: "cognito-idp.amazonaws.com" 114 | Action: 115 | - "sts:AssumeRole" 116 | Condition: 117 | StringEquals: 118 | sts:ExternalId: myampl84642f50_role_external_id 119 | Policies: 120 | - 121 | PolicyName: myampl84642f50-sns-policy 122 | PolicyDocument: 123 | Version: "2012-10-17" 124 | Statement: 125 | - 126 | Effect: "Allow" 127 | Action: 128 | - "sns:Publish" 129 | Resource: "*" 130 | # BEGIN USER POOL RESOURCES 131 | UserPool: 132 | # Created upon user selection 133 | # Depends on SNS Role for Arn if MFA is enabled 134 | Type: AWS::Cognito::UserPool 135 | UpdateReplacePolicy: Retain 136 | Properties: 137 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 138 | 139 | Schema: 140 | 141 | - 142 | Name: email 143 | Required: true 144 | Mutable: true 145 | 146 | 147 | 148 | 149 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 150 | 151 | 152 | EmailVerificationMessage: !Ref emailVerificationMessage 153 | EmailVerificationSubject: !Ref emailVerificationSubject 154 | 155 | Policies: 156 | PasswordPolicy: 157 | MinimumLength: !Ref passwordPolicyMinLength 158 | RequireLowercase: false 159 | RequireNumbers: false 160 | RequireSymbols: false 161 | RequireUppercase: false 162 | 163 | MfaConfiguration: !Ref mfaConfiguration 164 | SmsVerificationMessage: !Ref smsVerificationMessage 165 | SmsConfiguration: 166 | SnsCallerArn: !GetAtt SNSRole.Arn 167 | ExternalId: myampl84642f50_role_external_id 168 | 169 | 170 | UserPoolClientWeb: 171 | # Created provide application access to user pool 172 | # Depends on UserPool for ID reference 173 | Type: "AWS::Cognito::UserPoolClient" 174 | Properties: 175 | ClientName: myampl84642f50_app_clientWeb 176 | 177 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 178 | UserPoolId: !Ref UserPool 179 | DependsOn: UserPool 180 | UserPoolClient: 181 | # Created provide application access to user pool 182 | # Depends on UserPool for ID reference 183 | Type: "AWS::Cognito::UserPoolClient" 184 | Properties: 185 | ClientName: myampl84642f50_app_client 186 | 187 | GenerateSecret: !Ref userpoolClientGenerateSecret 188 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 189 | UserPoolId: !Ref UserPool 190 | DependsOn: UserPool 191 | # BEGIN USER POOL LAMBDA RESOURCES 192 | UserPoolClientRole: 193 | # Created to execute Lambda which gets userpool app client config values 194 | Type: 'AWS::IAM::Role' 195 | Properties: 196 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', '84642f50', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 197 | AssumeRolePolicyDocument: 198 | Version: '2012-10-17' 199 | Statement: 200 | - Effect: Allow 201 | Principal: 202 | Service: 203 | - lambda.amazonaws.com 204 | Action: 205 | - 'sts:AssumeRole' 206 | DependsOn: UserPoolClient 207 | UserPoolClientLambda: 208 | # Lambda which gets userpool app client config values 209 | # Depends on UserPool for id 210 | # Depends on UserPoolClientRole for role ARN 211 | Type: 'AWS::Lambda::Function' 212 | Properties: 213 | Code: 214 | ZipFile: !Join 215 | - |+ 216 | - - 'const response = require(''cfn-response'');' 217 | - 'const aws = require(''aws-sdk'');' 218 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 219 | - 'exports.handler = (event, context, callback) => {' 220 | - ' if (event.RequestType == ''Delete'') { ' 221 | - ' response.send(event, context, response.SUCCESS, {})' 222 | - ' }' 223 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 224 | - ' const params = {' 225 | - ' ClientId: event.ResourceProperties.clientId,' 226 | - ' UserPoolId: event.ResourceProperties.userpoolId' 227 | - ' };' 228 | - ' identity.describeUserPoolClient(params).promise()' 229 | - ' .then((res) => {' 230 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 231 | - ' })' 232 | - ' .catch((err) => {' 233 | - ' response.send(event, context, response.FAILED, {err});' 234 | - ' });' 235 | - ' }' 236 | - '};' 237 | Handler: index.handler 238 | Runtime: nodejs14.x 239 | Timeout: '300' 240 | Role: !GetAtt 241 | - UserPoolClientRole 242 | - Arn 243 | DependsOn: UserPoolClientRole 244 | UserPoolClientLambdaPolicy: 245 | # Sets userpool policy for the role that executes the Userpool Client Lambda 246 | # Depends on UserPool for Arn 247 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 248 | Type: 'AWS::IAM::Policy' 249 | Properties: 250 | PolicyName: myampl84642f50_userpoolclient_lambda_iam_policy 251 | Roles: 252 | - !Ref UserPoolClientRole 253 | PolicyDocument: 254 | Version: '2012-10-17' 255 | Statement: 256 | - Effect: Allow 257 | Action: 258 | - 'cognito-idp:DescribeUserPoolClient' 259 | Resource: !GetAtt UserPool.Arn 260 | DependsOn: UserPoolClientLambda 261 | UserPoolClientLogPolicy: 262 | # Sets log policy for the role that executes the Userpool Client Lambda 263 | # Depends on UserPool for Arn 264 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 265 | Type: 'AWS::IAM::Policy' 266 | Properties: 267 | PolicyName: myampl84642f50_userpoolclient_lambda_log_policy 268 | Roles: 269 | - !Ref UserPoolClientRole 270 | PolicyDocument: 271 | Version: 2012-10-17 272 | Statement: 273 | - Effect: Allow 274 | Action: 275 | - 'logs:CreateLogGroup' 276 | - 'logs:CreateLogStream' 277 | - 'logs:PutLogEvents' 278 | Resource: !Sub 279 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 280 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 281 | DependsOn: UserPoolClientLambdaPolicy 282 | UserPoolClientInputs: 283 | # Values passed to Userpool client Lambda 284 | # Depends on UserPool for Id 285 | # Depends on UserPoolClient for Id 286 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 287 | Type: 'Custom::LambdaCallout' 288 | Properties: 289 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 290 | clientId: !Ref UserPoolClient 291 | userpoolId: !Ref UserPool 292 | DependsOn: UserPoolClientLogPolicy 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | # BEGIN IDENTITY POOL RESOURCES 301 | 302 | 303 | IdentityPool: 304 | # Always created 305 | Type: AWS::Cognito::IdentityPool 306 | Properties: 307 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'myamplifyapp84642f50_identitypool_84642f50', !Join ['',['myamplifyapp84642f50_identitypool_84642f50', '__', !Ref env]]] 308 | 309 | CognitoIdentityProviders: 310 | - ClientId: !Ref UserPoolClient 311 | ProviderName: !Sub 312 | - cognito-idp.${region}.amazonaws.com/${client} 313 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 314 | - ClientId: !Ref UserPoolClientWeb 315 | ProviderName: !Sub 316 | - cognito-idp.${region}.amazonaws.com/${client} 317 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 318 | 319 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 320 | 321 | 322 | DependsOn: UserPoolClientInputs 323 | 324 | 325 | IdentityPoolRoleMap: 326 | # Created to map Auth and Unauth roles to the identity pool 327 | # Depends on Identity Pool for ID ref 328 | Type: AWS::Cognito::IdentityPoolRoleAttachment 329 | Properties: 330 | IdentityPoolId: !Ref IdentityPool 331 | Roles: 332 | unauthenticated: !Ref unauthRoleArn 333 | authenticated: !Ref authRoleArn 334 | DependsOn: IdentityPool 335 | 336 | 337 | Outputs : 338 | 339 | IdentityPoolId: 340 | Value: !Ref 'IdentityPool' 341 | Description: Id for the identity pool 342 | IdentityPoolName: 343 | Value: !GetAtt IdentityPool.Name 344 | 345 | 346 | 347 | 348 | UserPoolId: 349 | Value: !Ref 'UserPool' 350 | Description: Id for the user pool 351 | UserPoolName: 352 | Value: !Ref userPoolName 353 | AppClientIDWeb: 354 | Value: !Ref 'UserPoolClientWeb' 355 | Description: The user pool app client id for web 356 | AppClientID: 357 | Value: !Ref 'UserPoolClient' 358 | Description: The user pool app client id 359 | AppClientSecret: 360 | Value: !GetAtt UserPoolClientInputs.appSecret 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | -------------------------------------------------------------------------------- /amplify_code/amplify/backend/auth/myamplifyapp84642f50/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "myamplifyapp84642f50_identitypool_84642f50", 3 | "allowUnauthenticatedIdentities": false, 4 | "resourceNameTruncated": "myampl84642f50", 5 | "userPoolName": "myamplifyapp84642f50_userpool_84642f50", 6 | "autoVerifiedAttributes": [ 7 | "email" 8 | ], 9 | "mfaConfiguration": "OFF", 10 | "mfaTypes": [ 11 | "SMS Text Message" 12 | ], 13 | "smsAuthenticationMessage": "Your authentication code is {####}", 14 | "smsVerificationMessage": "Your verification code is {####}", 15 | "emailVerificationSubject": "Your verification code", 16 | "emailVerificationMessage": "Your verification code is {####}", 17 | "defaultPasswordPolicy": false, 18 | "passwordPolicyMinLength": 8, 19 | "passwordPolicyCharacters": [], 20 | "requiredAttributes": [ 21 | "email" 22 | ], 23 | "userpoolClientGenerateSecret": true, 24 | "userpoolClientRefreshTokenValidity": 30, 25 | "userpoolClientWriteAttributes": [ 26 | "email" 27 | ], 28 | "userpoolClientReadAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientLambdaRole": "myampl84642f50_userpoolclient_lambda_role", 32 | "userpoolClientSetAttributes": false, 33 | "sharedId": "84642f50", 34 | "resourceName": "myamplifyapp84642f50", 35 | "authSelections": "identityPoolAndUserPool", 36 | "authRoleArn": { 37 | "Fn::GetAtt": [ 38 | "AuthRole", 39 | "Arn" 40 | ] 41 | }, 42 | "unauthRoleArn": { 43 | "Fn::GetAtt": [ 44 | "UnauthRole", 45 | "Arn" 46 | ] 47 | }, 48 | "useDefault": "default", 49 | "userPoolGroupList": [], 50 | "dependsOn": [] 51 | } -------------------------------------------------------------------------------- /amplify_code/amplify/backend/auth/userPoolGroups/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "AuthRoleArn": { 3 | "Fn::GetAtt": [ 4 | "AuthRole", 5 | "Arn" 6 | ] 7 | }, 8 | "UnauthRoleArn": { 9 | "Fn::GetAtt": [ 10 | "UnauthRole", 11 | "Arn" 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /amplify_code/amplify/backend/auth/userPoolGroups/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Parameters": { 4 | "authmyamplifyapp84642f50UserPoolId": { 5 | "Type": "String", 6 | "Default": "authmyamplifyapp84642f50UserPoolId" 7 | }, 8 | 9 | "authmyamplifyapp84642f50IdentityPoolId": { 10 | "Type": "String", 11 | "Default": "authmyamplifyapp84642f50IdentityPoolId" 12 | }, 13 | 14 | "authmyamplifyapp84642f50AppClientID": { 15 | "Type": "String", 16 | "Default": "authmyamplifyapp84642f50AppClientID" 17 | }, 18 | "authmyamplifyapp84642f50AppClientIDWeb": { 19 | "Type": "String", 20 | "Default": "authmyamplifyapp84642f50AppClientIDWeb" 21 | }, 22 | "AuthRoleArn": { 23 | "Type": "String" 24 | }, 25 | "UnauthRoleArn": { 26 | "Type": "String" 27 | }, 28 | "env": { 29 | "Type": "String" 30 | } 31 | }, 32 | "Conditions": { 33 | "ShouldNotCreateEnvResources": { 34 | "Fn::Equals": [ 35 | { 36 | "Ref": "env" 37 | }, 38 | "NONE" 39 | ] 40 | } 41 | }, 42 | "Resources": { 43 | 44 | "adminGroup": { 45 | "Type" : "AWS::Cognito::UserPoolGroup", 46 | "Properties" : { 47 | "GroupName" : "admin", 48 | "Precedence" : 1, 49 | 50 | "RoleArn" : { 51 | "Fn::GetAtt": [ 52 | "adminGroupRole", 53 | "Arn" 54 | ] 55 | }, 56 | 57 | "UserPoolId" : { 58 | "Ref": "authmyamplifyapp84642f50UserPoolId" 59 | } 60 | } 61 | }, 62 | 63 | "adminGroupRole": { 64 | "Type": "AWS::IAM::Role", 65 | "Properties": { 66 | "RoleName":{ 67 | "Fn::Join": [ 68 | "", 69 | [ 70 | { 71 | "Ref": "authmyamplifyapp84642f50UserPoolId" 72 | }, 73 | "-adminGroupRole" 74 | ] 75 | ] 76 | }, 77 | "AssumeRolePolicyDocument": { 78 | "Version": "2012-10-17", 79 | "Statement": [ 80 | { 81 | "Sid": "", 82 | "Effect": "Allow", 83 | "Principal": { 84 | "Federated": "cognito-identity.amazonaws.com" 85 | }, 86 | "Action": "sts:AssumeRoleWithWebIdentity", 87 | "Condition": { 88 | "StringEquals": {"cognito-identity.amazonaws.com:aud": {"Ref":"authmyamplifyapp84642f50IdentityPoolId"}}, 89 | "ForAnyValue:StringLike": {"cognito-identity.amazonaws.com:amr": "authenticated"} 90 | } 91 | } 92 | ] 93 | } 94 | } 95 | }, 96 | 97 | 98 | 99 | "LambdaExecutionRole": { 100 | "Type": "AWS::IAM::Role", 101 | "Properties": { 102 | "RoleName": { 103 | "Fn::If": [ 104 | "ShouldNotCreateEnvResources", 105 | { 106 | 107 | }, 108 | { 109 | 110 | "Fn::Join": [ 111 | "", 112 | [ 113 | 114 | "myamplifyapp84642f50", 115 | "-ExecutionRole-", 116 | { 117 | "Ref": "env" 118 | } 119 | ] 120 | ] 121 | } 122 | ] 123 | }, 124 | "AssumeRolePolicyDocument": { 125 | "Version": "2012-10-17", 126 | "Statement": [ 127 | { 128 | "Effect": "Allow", 129 | "Principal": { 130 | "Service": [ 131 | "lambda.amazonaws.com" 132 | ] 133 | }, 134 | "Action": [ 135 | "sts:AssumeRole" 136 | ] 137 | } 138 | ] 139 | }, 140 | "Policies": [ 141 | { 142 | "PolicyName": "UserGroupLogPolicy", 143 | "PolicyDocument": { 144 | "Version": "2012-10-17", 145 | "Statement": [ 146 | { 147 | "Effect": "Allow", 148 | "Action": [ 149 | "logs:CreateLogGroup", 150 | "logs:CreateLogStream", 151 | "logs:PutLogEvents" 152 | ], 153 | "Resource": "arn:aws:logs:*:*:*" 154 | } 155 | ] 156 | } 157 | }, 158 | { 159 | "PolicyName": "UserGroupExecutionPolicy", 160 | "PolicyDocument": { 161 | "Version": "2012-10-17", 162 | "Statement": [ 163 | { 164 | "Effect": "Allow", 165 | "Action": [ 166 | "cognito-identity:SetIdentityPoolRoles", 167 | "cognito-identity:ListIdentityPools", 168 | "cognito-identity:describeIdentityPool" 169 | 170 | ], 171 | "Resource": "*" 172 | } 173 | ] 174 | } 175 | }, 176 | { 177 | "PolicyName": "UserGroupPassRolePolicy", 178 | "PolicyDocument": { 179 | "Version": "2012-10-17", 180 | "Statement": [ 181 | { 182 | "Effect": "Allow", 183 | "Action": [ 184 | "iam:PassRole" 185 | ], 186 | "Resource": "*" 187 | } 188 | ] 189 | } 190 | } 191 | ] 192 | } 193 | }, 194 | "RoleMapFunction": { 195 | "Type": "AWS::Lambda::Function", 196 | "DependsOn": ["LambdaExecutionRole"], 197 | "Properties": { 198 | "Code": { 199 | "ZipFile": { 200 | "Fn::Join": [ 201 | "\n", 202 | [ 203 | "const response = require('cfn-response');", 204 | "const AWS = require('aws-sdk');", 205 | "exports.handler = (event, context) => {", 206 | "if (event.RequestType == 'Delete') {", 207 | " response.send(event, context, response.SUCCESS, {message: 'Request type delete'})", 208 | "};", 209 | "if (event.RequestType == 'Create' || event.RequestType == 'Update') {", 210 | " let { identityPoolId, appClientID, appClientIDWeb, userPoolId, region } = event.ResourceProperties;", 211 | " try {", 212 | " const cognitoidentity = new AWS.CognitoIdentity();", 213 | " let params = {", 214 | " IdentityPoolId: identityPoolId,", 215 | " Roles: {", 216 | " 'authenticated': event.ResourceProperties.AuthRoleArn,", 217 | " 'unauthenticated': event.ResourceProperties.UnauthRoleArn,", 218 | " },", 219 | " RoleMappings: {}", 220 | " };", 221 | " if (appClientIDWeb) {", 222 | " params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientIDWeb}`] = {", 223 | " Type: 'Token',", 224 | " AmbiguousRoleResolution: 'AuthenticatedRole',", 225 | " }", 226 | " }", 227 | " if (appClientID) {", 228 | " params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientID}`] = {", 229 | " Type: 'Token',", 230 | " AmbiguousRoleResolution: 'AuthenticatedRole',", 231 | " }", 232 | " }", 233 | " cognitoidentity.setIdentityPoolRoles(params).promise();", 234 | " response.send(event, context, response.SUCCESS, {message: 'Successfully updated identity pool.'})", 235 | " } catch(err) {", 236 | 237 | " response.send(event, context, response.FAILED, {message: 'Error updating identity pool'});", 238 | " }", 239 | " };", 240 | "};" 241 | 242 | ] 243 | ] 244 | } 245 | }, 246 | "Handler": "index.handler", 247 | "Runtime": "nodejs14.x", 248 | "Timeout": "300", 249 | "Role": { 250 | "Fn::GetAtt": [ 251 | "LambdaExecutionRole", 252 | "Arn" 253 | ] 254 | } 255 | } 256 | }, 257 | "RoleMapFunctionInput": { 258 | "Type": "Custom::LambdaCallout", 259 | "Properties": { 260 | "ServiceToken": { 261 | "Fn::GetAtt": [ 262 | "RoleMapFunction", 263 | "Arn" 264 | ] 265 | }, 266 | "AuthRoleArn": { 267 | "Ref": "AuthRoleArn" 268 | }, 269 | "UnauthRoleArn": { 270 | "Ref": "UnauthRoleArn" 271 | }, 272 | "identityPoolId": { 273 | "Ref": "authmyamplifyapp84642f50IdentityPoolId" 274 | }, 275 | "userPoolId": { 276 | "Ref": "authmyamplifyapp84642f50UserPoolId" 277 | }, 278 | "appClientIDWeb": { 279 | "Ref": "authmyamplifyapp84642f50AppClientIDWeb" 280 | }, 281 | "appClientID": { 282 | "Ref": "authmyamplifyapp84642f50AppClientID" 283 | }, 284 | "region": { 285 | "Ref": "AWS::Region" 286 | }, 287 | "env": { 288 | "Ref": "env" 289 | } 290 | }, 291 | "DependsOn": ["RoleMapFunction"] 292 | } 293 | 294 | }, 295 | 296 | "Outputs": { 297 | 298 | "adminGroupRole": { 299 | "Value": { 300 | "Fn::GetAtt": [ 301 | "adminGroupRole", 302 | "Arn" 303 | ] 304 | } 305 | 306 | } 307 | 308 | 309 | } 310 | 311 | } 312 | -------------------------------------------------------------------------------- /amplify_code/amplify/backend/auth/userPoolGroups/user-pool-group-precedence.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "groupName": "admin", 4 | "precedence": 1 5 | } 6 | ] -------------------------------------------------------------------------------- /amplify_code/amplify/backend/awscloudformation/nested-cloudformation-stack.yml: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Root stack for the Amplify AWS CloudFormation provider", 4 | "Parameters": { 5 | "DeploymentBucketName": { 6 | "Description": "Name of the common deployment bucket provided by the parent stack", 7 | "Type": "String", 8 | "Default": "DeploymentBucket" 9 | }, 10 | "AuthRoleName": { 11 | "Type": "String", 12 | "Default": "AuthRoleName" 13 | }, 14 | "UnauthRoleName": { 15 | "Type": "String", 16 | "Default": "UnauthRoleName" 17 | } 18 | }, 19 | "Resources": { 20 | "DeploymentBucket": { 21 | "Type": "AWS::S3::Bucket", 22 | "DeletionPolicy": "Retain", 23 | "Properties": { 24 | "BucketName": { 25 | "Ref": "DeploymentBucketName" 26 | } 27 | } 28 | }, 29 | "AuthRole": { 30 | "Type": "AWS::IAM::Role", 31 | "Properties": { 32 | "RoleName": { 33 | "Ref": "AuthRoleName" 34 | }, 35 | "AssumeRolePolicyDocument": { 36 | "Version": "2012-10-17", 37 | "Statement": [ 38 | { 39 | "Sid": "", 40 | "Effect": "Deny", 41 | "Principal": { 42 | "Federated": "cognito-identity.amazonaws.com" 43 | }, 44 | "Action": "sts:AssumeRoleWithWebIdentity" 45 | } 46 | ] 47 | } 48 | } 49 | }, 50 | "UnauthRole": { 51 | "Type": "AWS::IAM::Role", 52 | "Properties": { 53 | "RoleName": { 54 | "Ref": "UnauthRoleName" 55 | }, 56 | "AssumeRolePolicyDocument": { 57 | "Version": "2012-10-17", 58 | "Statement": [ 59 | { 60 | "Sid": "", 61 | "Effect": "Deny", 62 | "Principal": { 63 | "Federated": "cognito-identity.amazonaws.com" 64 | }, 65 | "Action": "sts:AssumeRoleWithWebIdentity" 66 | } 67 | ] 68 | } 69 | } 70 | }, 71 | "authmyamplifyapp84642f50": { 72 | "Type": "AWS::CloudFormation::Stack", 73 | "Properties": { 74 | "TemplateURL": "https://s3.amazonaws.com/amplify-myamplifyapp-dev-143204-deployment/amplify-cfn-templates/auth/myamplifyapp84642f50-cloudformation-template.yml", 75 | "Parameters": { 76 | "identityPoolName": "myamplifyapp84642f50_identitypool_84642f50", 77 | "allowUnauthenticatedIdentities": false, 78 | "resourceNameTruncated": "myampl84642f50", 79 | "userPoolName": "myamplifyapp84642f50_userpool_84642f50", 80 | "autoVerifiedAttributes": "email", 81 | "mfaConfiguration": "OFF", 82 | "mfaTypes": "SMS Text Message", 83 | "smsAuthenticationMessage": "Your authentication code is {####}", 84 | "smsVerificationMessage": "Your verification code is {####}", 85 | "emailVerificationSubject": "Your verification code", 86 | "emailVerificationMessage": "Your verification code is {####}", 87 | "defaultPasswordPolicy": false, 88 | "passwordPolicyMinLength": 8, 89 | "passwordPolicyCharacters": "", 90 | "requiredAttributes": "email", 91 | "userpoolClientGenerateSecret": true, 92 | "userpoolClientRefreshTokenValidity": 30, 93 | "userpoolClientWriteAttributes": "email", 94 | "userpoolClientReadAttributes": "email", 95 | "userpoolClientLambdaRole": "myampl84642f50_userpoolclient_lambda_role", 96 | "userpoolClientSetAttributes": false, 97 | "sharedId": "84642f50", 98 | "resourceName": "myamplifyapp84642f50", 99 | "authSelections": "identityPoolAndUserPool", 100 | "authRoleArn": { 101 | "Fn::GetAtt": [ 102 | "AuthRole", 103 | "Arn" 104 | ] 105 | }, 106 | "unauthRoleArn": { 107 | "Fn::GetAtt": [ 108 | "UnauthRole", 109 | "Arn" 110 | ] 111 | }, 112 | "useDefault": "default", 113 | "userPoolGroupList": "", 114 | "dependsOn": "", 115 | "env": "dev" 116 | } 117 | } 118 | }, 119 | "authuserPoolGroups": { 120 | "Type": "AWS::CloudFormation::Stack", 121 | "Properties": { 122 | "TemplateURL": "https://s3.amazonaws.com/amplify-myamplifyapp-dev-143204-deployment/amplify-cfn-templates/auth/template.json", 123 | "Parameters": { 124 | "AuthRoleArn": { 125 | "Fn::GetAtt": [ 126 | "AuthRole", 127 | "Arn" 128 | ] 129 | }, 130 | "UnauthRoleArn": { 131 | "Fn::GetAtt": [ 132 | "UnauthRole", 133 | "Arn" 134 | ] 135 | }, 136 | "authmyamplifyapp84642f50UserPoolId": { 137 | "Fn::GetAtt": [ 138 | "authmyamplifyapp84642f50", 139 | "Outputs.UserPoolId" 140 | ] 141 | }, 142 | "authmyamplifyapp84642f50AppClientIDWeb": { 143 | "Fn::GetAtt": [ 144 | "authmyamplifyapp84642f50", 145 | "Outputs.AppClientIDWeb" 146 | ] 147 | }, 148 | "authmyamplifyapp84642f50AppClientID": { 149 | "Fn::GetAtt": [ 150 | "authmyamplifyapp84642f50", 151 | "Outputs.AppClientID" 152 | ] 153 | }, 154 | "authmyamplifyapp84642f50IdentityPoolId": { 155 | "Fn::GetAtt": [ 156 | "authmyamplifyapp84642f50", 157 | "Outputs.IdentityPoolId" 158 | ] 159 | }, 160 | "env": "dev" 161 | } 162 | } 163 | }, 164 | "UpdateRolesWithIDPFunction": { 165 | "DependsOn": [ 166 | "AuthRole", 167 | "UnauthRole", 168 | "authmyamplifyapp84642f50" 169 | ], 170 | "Type": "AWS::Lambda::Function", 171 | "Properties": { 172 | "Code": { 173 | "ZipFile": { 174 | "Fn::Join": [ 175 | "\n", 176 | [ 177 | "const response = require('cfn-response');", 178 | "const aws = require('aws-sdk');", 179 | "let responseData = {};", 180 | "exports.handler = function(event, context) {", 181 | " try {", 182 | " let authRoleName = event.ResourceProperties.authRoleName;", 183 | " let unauthRoleName = event.ResourceProperties.unauthRoleName;", 184 | " let idpId = event.ResourceProperties.idpId;", 185 | " let promises = [];", 186 | " let authParamsJson = { 'Version': '2012-10-17','Statement': [{'Effect': 'Allow','Principal': {'Federated': 'cognito-identity.amazonaws.com'},'Action': 'sts:AssumeRoleWithWebIdentity','Condition': {'StringEquals': {'cognito-identity.amazonaws.com:aud': idpId},'ForAnyValue:StringLike': {'cognito-identity.amazonaws.com:amr': 'authenticated'}}}]};", 187 | " let unauthParamsJson = { 'Version': '2012-10-17','Statement': [{'Effect': 'Allow','Principal': {'Federated': 'cognito-identity.amazonaws.com'},'Action': 'sts:AssumeRoleWithWebIdentity','Condition': {'StringEquals': {'cognito-identity.amazonaws.com:aud': idpId},'ForAnyValue:StringLike': {'cognito-identity.amazonaws.com:amr': 'unauthenticated'}}}]};", 188 | " if (event.RequestType == 'Delete') {", 189 | " delete authParamsJson.Statement.Condition;", 190 | " delete unauthParamsJson.Statement.Condition;", 191 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 192 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 193 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 194 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 195 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 196 | " Promise.all(promises)", 197 | " .then((res) => {", 198 | " console.log(\"delete response data\" + JSON.stringify(res));", 199 | " response.send(event, context, response.SUCCESS, {});", 200 | " });", 201 | " }", 202 | " if (event.RequestType == 'Update' || event.RequestType == 'Create') {", 203 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 204 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 205 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 206 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 207 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 208 | " Promise.all(promises)", 209 | " .then((res) => {", 210 | " console.log(\"createORupdate\" + res);", 211 | " console.log(\"response data\" + JSON.stringify(res));", 212 | " response.send(event, context, response.SUCCESS, {});", 213 | " });", 214 | " }", 215 | " } catch(err) {", 216 | " console.log(err.stack);", 217 | " responseData = {Error: err};", 218 | " response.send(event, context, response.FAILED, responseData);", 219 | " throw err;", 220 | " }", 221 | "};" 222 | ] 223 | ] 224 | } 225 | }, 226 | "Handler": "index.handler", 227 | "Runtime": "nodejs14.x", 228 | "Timeout": "300", 229 | "Role": { 230 | "Fn::GetAtt": [ 231 | "UpdateRolesWithIDPFunctionRole", 232 | "Arn" 233 | ] 234 | } 235 | } 236 | }, 237 | "UpdateRolesWithIDPFunctionOutputs": { 238 | "Type": "Custom::LambdaCallout", 239 | "Properties": { 240 | "ServiceToken": { 241 | "Fn::GetAtt": [ 242 | "UpdateRolesWithIDPFunction", 243 | "Arn" 244 | ] 245 | }, 246 | "region": { 247 | "Ref": "AWS::Region" 248 | }, 249 | "idpId": { 250 | "Fn::GetAtt": [ 251 | "authmyamplifyapp84642f50", 252 | "Outputs.IdentityPoolId" 253 | ] 254 | }, 255 | "authRoleName": { 256 | "Ref": "AuthRoleName" 257 | }, 258 | "unauthRoleName": { 259 | "Ref": "UnauthRoleName" 260 | } 261 | } 262 | }, 263 | "UpdateRolesWithIDPFunctionRole": { 264 | "Type": "AWS::IAM::Role", 265 | "Properties": { 266 | "RoleName": { 267 | "Fn::Join": [ 268 | "", 269 | [ 270 | { 271 | "Ref": "AuthRoleName" 272 | }, 273 | "-idp" 274 | ] 275 | ] 276 | }, 277 | "AssumeRolePolicyDocument": { 278 | "Version": "2012-10-17", 279 | "Statement": [ 280 | { 281 | "Effect": "Allow", 282 | "Principal": { 283 | "Service": [ 284 | "lambda.amazonaws.com" 285 | ] 286 | }, 287 | "Action": [ 288 | "sts:AssumeRole" 289 | ] 290 | } 291 | ] 292 | }, 293 | "Policies": [ 294 | { 295 | "PolicyName": "UpdateRolesWithIDPFunctionPolicy", 296 | "PolicyDocument": { 297 | "Version": "2012-10-17", 298 | "Statement": [ 299 | { 300 | "Effect": "Allow", 301 | "Action": [ 302 | "logs:CreateLogGroup", 303 | "logs:CreateLogStream", 304 | "logs:PutLogEvents" 305 | ], 306 | "Resource": "arn:aws:logs:*:*:*" 307 | }, 308 | { 309 | "Effect": "Allow", 310 | "Action": "iam:UpdateAssumeRolePolicy", 311 | "Resource": { 312 | "Fn::GetAtt": [ 313 | "AuthRole", 314 | "Arn" 315 | ] 316 | } 317 | }, 318 | { 319 | "Effect": "Allow", 320 | "Action": "iam:UpdateAssumeRolePolicy", 321 | "Resource": { 322 | "Fn::GetAtt": [ 323 | "UnauthRole", 324 | "Arn" 325 | ] 326 | } 327 | } 328 | ] 329 | } 330 | } 331 | ] 332 | } 333 | } 334 | }, 335 | "Outputs": { 336 | "Region": { 337 | "Description": "CloudFormation provider root stack Region", 338 | "Value": { 339 | "Ref": "AWS::Region" 340 | }, 341 | "Export": { 342 | "Name": { 343 | "Fn::Sub": "${AWS::StackName}-Region" 344 | } 345 | } 346 | }, 347 | "StackName": { 348 | "Description": "CloudFormation provider root stack ID", 349 | "Value": { 350 | "Ref": "AWS::StackName" 351 | }, 352 | "Export": { 353 | "Name": { 354 | "Fn::Sub": "${AWS::StackName}-StackName" 355 | } 356 | } 357 | }, 358 | "StackId": { 359 | "Description": "CloudFormation provider root stack name", 360 | "Value": { 361 | "Ref": "AWS::StackId" 362 | }, 363 | "Export": { 364 | "Name": { 365 | "Fn::Sub": "${AWS::StackName}-StackId" 366 | } 367 | } 368 | }, 369 | "DeploymentBucketName": { 370 | "Description": "CloudFormation provider root stack deployment bucket name", 371 | "Value": { 372 | "Ref": "DeploymentBucketName" 373 | }, 374 | "Export": { 375 | "Name": { 376 | "Fn::Sub": "${AWS::StackName}-DeploymentBucketName" 377 | } 378 | } 379 | }, 380 | "AuthRoleArn": { 381 | "Value": { 382 | "Fn::GetAtt": [ 383 | "AuthRole", 384 | "Arn" 385 | ] 386 | } 387 | }, 388 | "UnauthRoleArn": { 389 | "Value": { 390 | "Fn::GetAtt": [ 391 | "UnauthRole", 392 | "Arn" 393 | ] 394 | } 395 | }, 396 | "AuthRoleName": { 397 | "Value": { 398 | "Ref": "AuthRole" 399 | } 400 | }, 401 | "UnauthRoleName": { 402 | "Value": { 403 | "Ref": "UnauthRole" 404 | } 405 | } 406 | } 407 | } 408 | -------------------------------------------------------------------------------- /amplify_code/amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "myamplifyapp84642f50": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [], 7 | "customAuth": false 8 | }, 9 | "userPoolGroups": { 10 | "service": "Cognito-UserPool-Groups", 11 | "providerPlugin": "awscloudformation", 12 | "dependsOn": [ 13 | { 14 | "category": "auth", 15 | "resourceName": "myamplifyapp84642f50", 16 | "attributes": [ 17 | "UserPoolId", 18 | "AppClientIDWeb", 19 | "AppClientID", 20 | "IdentityPoolId" 21 | ] 22 | } 23 | ] 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /amplify_code/amplify/team-provider-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "dev": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplify-myamplifyapp-dev-143204-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::109499523128:role/amplify-myamplifyapp-dev-143204-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::109499523128:role/amplify-myamplifyapp-dev-143204-authRole", 7 | "Region": "us-west-2", 8 | "DeploymentBucketName": "amplify-myamplifyapp-dev-143204-deployment", 9 | "UnauthRoleName": "amplify-myamplifyapp-dev-143204-unauthRole", 10 | "StackName": "amplify-myamplifyapp-dev-143204", 11 | "StackId": "arn:aws:cloudformation:us-west-2:109499523128:stack/amplify-myamplifyapp-dev-143204/4eb1b5e0-c099-11ea-9286-02b0d23de91c", 12 | "AmplifyAppId": "d2o2lsbvokqla0" 13 | }, 14 | "categories": { 15 | "auth": { 16 | "myamplifyapp84642f50": {} 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /amplify_code/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "myamplifyapp", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.5.0", 8 | "@testing-library/user-event": "^7.2.1", 9 | "aws-amplify": "^3.0.19", 10 | "aws-amplify-react": "^4.1.18", 11 | "bootstrap": "^4.5.0", 12 | "react": "^16.13.1", 13 | "react-bootstrap": "^1.1.1", 14 | "react-dom": "^16.13.1", 15 | "react-scripts": "3.4.1" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": "react-app" 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /amplify_code/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_code/public/favicon.ico -------------------------------------------------------------------------------- /amplify_code/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /amplify_code/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_code/public/logo192.png -------------------------------------------------------------------------------- /amplify_code/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_code/public/logo512.png -------------------------------------------------------------------------------- /amplify_code/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /amplify_code/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /amplify_code/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /amplify_code/src/App.js: -------------------------------------------------------------------------------- 1 | import Amplify, { Auth, API } from 'aws-amplify'; 2 | import { withAuthenticator } from 'aws-amplify-react'; 3 | import React, { Component } from 'react'; 4 | import awsconfig from './aws-exports'; 5 | import '@aws-amplify/ui/dist/style.css'; 6 | import { PubSub } from 'aws-amplify'; 7 | import { AWSIoTProvider } from '@aws-amplify/pubsub/lib/Providers'; 8 | import 'bootstrap/dist/css/bootstrap.min.css'; 9 | import logo from './logo.svg'; 10 | Amplify.configure(awsconfig); 11 | 12 | var SUB_TOPIC = "esp32/pub"; 13 | var PUB_TOPIC = "esp32/sub"; 14 | 15 | // Apply plugin with configuration 16 | Amplify.addPluggable(new AWSIoTProvider({ 17 | aws_pubsub_region: '', 18 | aws_pubsub_endpoint: 'wss://xxxxxxxxxxxxx.iot..amazonaws.com/mqtt', 19 | })); 20 | 21 | async function ProcessMessage(payload) { 22 | console.log('Message received', payload); 23 | let topic=payload.value[Object.getOwnPropertySymbols(payload.value)[0]]; 24 | let time=payload.value.time; 25 | let sensor_a0=payload.value.sensor_a0; 26 | let scrollBox = document.getElementById('incomingMsg'); 27 | scrollBox.innerHTML += "NEW MESSAGE:

Topic: " + topic + "

Time: " + time + "

Sensor_a0: " + sensor_a0 + "

"; 28 | scrollBox.scrollTop = scrollBox.scrollHeight; 29 | } 30 | 31 | async function SendMessage() { 32 | let payload=document.getElementById('msg').value; 33 | document.getElementById('msg').value=''; 34 | console.log(payload); 35 | await PubSub.publish(PUB_TOPIC, { msg: payload }); 36 | document.getElementById('returnMsg').innerHTML = '

Message sent!

'; 37 | let sentMsgBox = document.getElementById('sentMsg'); 38 | sentMsgBox.innerHTML += payload + "

"; 39 | sentMsgBox.scrollTop = sentMsgBox.scrollHeight; 40 | } 41 | 42 | function App() { 43 | subscribe(); 44 | return ( 45 |
46 |
47 | logo 48 |

IoT Messaging

49 | Powered by AWS Cloud Computing 50 |
51 |
52 |
53 |

Publisher

54 |

The box below can be used to publish messages back to your devices by publishing to the topic {PUB_TOPIC}

55 |
Message:
56 | 57 |

58 | 59 |
60 |

61 |

Sent Messages:

62 |

Your sent messages will appear here

63 |
64 |
65 |



66 |
67 |

Subscriber

68 |

New messages from your device(s) that publish to the topic {SUB_TOPIC} will appear in the box below

69 |
70 |
71 |
72 |
73 | ); 74 | } 75 | 76 | function subscribe() { 77 | PubSub.subscribe(SUB_TOPIC).subscribe({ 78 | next: data => ProcessMessage(data), 79 | error: error => console.error(error), 80 | close: () => console.log('Done'), 81 | }); 82 | } 83 | 84 | export default withAuthenticator(App, true); 85 | 86 | -------------------------------------------------------------------------------- /amplify_code/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /amplify_code/src/aws-exports.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten. 3 | 4 | const awsmobile = { 5 | "aws_project_region": "us-west-2", 6 | "aws_cognito_identity_pool_id": "us-west-2:b4b257fb-fa4f-45bd-9ae0-bf0743af5da0", 7 | "aws_cognito_region": "us-west-2", 8 | "aws_user_pools_id": "us-west-2_FHcBMjfC6", 9 | "aws_user_pools_web_client_id": "lc2la0msvfu0jjc474b77c1nj", 10 | "oauth": {} 11 | }; 12 | 13 | 14 | export default awsmobile; 15 | -------------------------------------------------------------------------------- /amplify_code/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /amplify_code/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /amplify_code/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /amplify_code/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /amplify_code/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /amplify_pictures/AmplifyAddAuth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyAddAuth.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyAddHosting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyAddHosting.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyAddUserPool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyAddUserPool.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyAttachPolicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyAttachPolicy.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyAuthPerms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyAuthPerms.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyAuthRole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyAuthRole.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyBlankApp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyBlankApp.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyCLIConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyCLIConfig.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyCognitoGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyCognitoGroup.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyCognitoIdentities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyCognitoIdentities.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyCognitoIdentityID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyCognitoIdentityID.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyCognitoUser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyCognitoUser.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyConfigureEnter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyConfigureEnter.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyDeviceConnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyDeviceConnected.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyEmptyApp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyEmptyApp.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyIAMAddUser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyIAMAddUser.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyIAMPolicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyIAMPolicy.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyIAMSuccess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyIAMSuccess.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyIAMTags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyIAMTags.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyIOTPolicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyIOTPolicy.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyIncomingMsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyIncomingMsg.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyInit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyInit.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyMsgReceived.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyMsgReceived.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyParentStack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyParentStack.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyPublish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyPublish.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyPush.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyPush.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifySendMsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifySendMsg.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifySentMsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifySentMsg.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifySignInPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifySignInPage.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifySignInUser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifySignInUser.png -------------------------------------------------------------------------------- /amplify_pictures/AmplifyURL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/amplify_pictures/AmplifyURL.png -------------------------------------------------------------------------------- /iot_code/DemoProject/include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /iot_code/DemoProject/include/secrets.h: -------------------------------------------------------------------------------- 1 | #include 2 | #define SECRET 3 | #define THINGNAME "ESP32" 4 | const char WIFI_SSID[] = ""; 5 | const char WIFI_PASSWORD[] = ""; 6 | const char AWS_IOT_ENDPOINT[] = ""; 7 | // Amazon Root CA 1 8 | static const char AWS_CERT_CA[] PROGMEM = R"EOF( 9 | -----BEGIN CERTIFICATE----- 10 | // insert AWS root CA 1 cert here 11 | -----END CERTIFICATE----- 12 | )EOF"; 13 | // Device Certificate 14 | static const char AWS_CERT_CRT[] PROGMEM = R"KEY( 15 | -----BEGIN CERTIFICATE----- 16 | // insert device certificate here 17 | -----END CERTIFICATE----- 18 | )KEY"; 19 | // Device Private Key 20 | static const char AWS_CERT_PRIVATE[] PROGMEM = R"KEY( 21 | -----BEGIN RSA PRIVATE KEY----- 22 | // insert device private key here 23 | -----END RSA PRIVATE KEY----- 24 | )KEY"; -------------------------------------------------------------------------------- /iot_code/DemoProject/lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /iot_code/DemoProject/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:esp32dev] 12 | platform = espressif32 13 | board = esp32dev 14 | framework = arduino -------------------------------------------------------------------------------- /iot_code/DemoProject/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../include/secrets.h" 3 | #include 4 | #include 5 | #include 6 | #include "WiFi.h" 7 | 8 | // The MQTT topics that this device should publish/subscribe 9 | #define AWS_IOT_PUBLISH_TOPIC "esp32/pub" 10 | #define AWS_IOT_SUBSCRIBE_TOPIC "esp32/sub" 11 | 12 | WiFiClientSecure net = WiFiClientSecure(); 13 | MQTTClient client = MQTTClient(256); 14 | 15 | void messageHandler(String &topic, String &payload) { 16 | Serial.println("incoming: " + topic + " - " + payload); 17 | } 18 | 19 | void connectAWS() 20 | { 21 | WiFi.mode(WIFI_STA); 22 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 23 | 24 | Serial.println("Connecting to Wi-Fi"); 25 | 26 | while (WiFi.status() != WL_CONNECTED){ 27 | delay(500); 28 | Serial.print("."); 29 | } 30 | 31 | // Configure WiFiClientSecure to use the AWS IoT device credentials 32 | net.setCACert(AWS_CERT_CA); 33 | net.setCertificate(AWS_CERT_CRT); 34 | net.setPrivateKey(AWS_CERT_PRIVATE); 35 | 36 | // Connect to the MQTT broker on the AWS endpoint we defined earlier 37 | client.begin(AWS_IOT_ENDPOINT, 8883, net); 38 | 39 | // Create a message handler 40 | client.onMessage(messageHandler); 41 | 42 | Serial.print("Connecting to AWS IOT"); 43 | 44 | while (!client.connect(THINGNAME)) { 45 | Serial.print("."); 46 | delay(100); 47 | } 48 | 49 | if(!client.connected()){ 50 | Serial.println("AWS IoT Timeout!"); 51 | return; 52 | } 53 | 54 | // Subscribe to a topic 55 | client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC); 56 | 57 | Serial.println("AWS IoT Connected!"); 58 | } 59 | 60 | void publishMessage() 61 | { 62 | StaticJsonDocument<200> doc; 63 | doc["time"] = millis(); 64 | doc["sensor_a0"] = analogRead(0); 65 | char jsonBuffer[512]; 66 | serializeJson(doc, jsonBuffer); // print to client 67 | 68 | client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer); 69 | } 70 | 71 | void setup() { 72 | Serial.begin(9600); 73 | connectAWS(); 74 | } 75 | 76 | void loop() { 77 | publishMessage(); 78 | client.loop(); 79 | delay(1000); 80 | } -------------------------------------------------------------------------------- /iot_code/DemoProject/test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PIO Unit Testing and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PIO Unit Testing: 11 | - https://docs.platformio.org/page/plus/unit-testing.html 12 | -------------------------------------------------------------------------------- /iot_pictures/IoT Core Add device to Registry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Add device to Registry.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Attach Policy Choose Pol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Attach Policy Choose Pol.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Attach Policy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Attach Policy.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Certificate Created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Certificate Created.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Certificates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Certificates.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Confirm Cert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Confirm Cert.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Create Policy with any resource in account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Create Policy with any resource in account.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Create a Single Thing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Create a Single Thing.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core How to Get AccountID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core How to Get AccountID.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core How to Get Region.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core How to Get Region.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Manage Tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Manage Tab.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Secure Tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Secure Tab.png -------------------------------------------------------------------------------- /iot_pictures/IoT Core Skip Attach Policy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoT Core Skip Attach Policy.png -------------------------------------------------------------------------------- /iot_pictures/IoTConsoleTestPub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoTConsoleTestPub.png -------------------------------------------------------------------------------- /iot_pictures/IoTConsoleTestSub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoTConsoleTestSub.png -------------------------------------------------------------------------------- /iot_pictures/IoTConsoleTestSubPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoTConsoleTestSubPage.png -------------------------------------------------------------------------------- /iot_pictures/IoTCorePolicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoTCorePolicy.png -------------------------------------------------------------------------------- /iot_pictures/IoTTestSub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/IoTTestSub.png -------------------------------------------------------------------------------- /iot_pictures/PlatformIO AJ Library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/PlatformIO AJ Library.png -------------------------------------------------------------------------------- /iot_pictures/PlatformIO Bottom Bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/PlatformIO Bottom Bar.png -------------------------------------------------------------------------------- /iot_pictures/PlatformIO Install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/PlatformIO Install.png -------------------------------------------------------------------------------- /iot_pictures/PlatformIO MQTT Library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/PlatformIO MQTT Library.png -------------------------------------------------------------------------------- /iot_pictures/PlatformIO New Project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/PlatformIO New Project.png -------------------------------------------------------------------------------- /iot_pictures/PlatformIO Project Options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/PlatformIO Project Options.png -------------------------------------------------------------------------------- /iot_pictures/ProjectArch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/ProjectArch.png -------------------------------------------------------------------------------- /iot_pictures/ProjectArch2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/ProjectArch2.png -------------------------------------------------------------------------------- /iot_pictures/ProjectArch3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/ProjectArch3.png -------------------------------------------------------------------------------- /iot_pictures/ProjectArchV3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/ProjectArchV3.png -------------------------------------------------------------------------------- /iot_pictures/ProjectArchV4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/ProjectArchV4.png -------------------------------------------------------------------------------- /iot_pictures/Serial Monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/Serial Monitor.png -------------------------------------------------------------------------------- /iot_pictures/Successful Flash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-end-to-end-iot-amplify-demo/b6c27863c72fd4b902c95e2c600d00fabb42f667/iot_pictures/Successful Flash.png --------------------------------------------------------------------------------