|
| 1 | +# Optional Module 2 Extension: Serverless APIs with IAM-based Authorization |
| 2 | + |
| 3 | +In this **optional extension to module 2**, you will update your serverless backend for your Wild Rydes application leveraging [Amazon API Gateway](https://aws.amazon.com/api-gateway/) and [AWS Lambda](https://aws.amazon.com/lambda/) to use IAM-based authorization as a more secure authentication option which includes request signing. |
| 4 | + |
| 5 | +**If you would like to skip this optional extension**, you are able to proceed to module 3, [IAM-based Authorization](../3_IAMAuthorization). |
| 6 | + |
| 7 | +## Solution Architecture |
| 8 | + |
| 9 | +Building on Module 2, this module updates our Serverless backend built earlier using Amazon API Gateway and AWS Lambda to use IAM-based authorization. This extends our authorization capability to offer fine-grained access control authorizing differently per API operation and enhancing security via request signing. By enabling IAM-based authorization, you will use the same type of authentication, authorization, and request signing used by all AWS services and SDKs. |
| 10 | + |
| 11 | +[Request signing](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html) is a more secure implementation of API request authentication where each API request made is signed with a signature unique to the request itself. Hence, no static API keys or bearer tokens are directly sent to the backend service and any man-in-the-middle attacks would not be able to use such API keys or bearer tokens to impersonate a valid user with the backend resources. AWS APIs and SDKs use a request signing algorithm nammed [Signature V4 (Sigv4)](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) which is what you will enable your API to use in this module. |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +## Implementation Overview |
| 16 | + |
| 17 | +Each of the following sections provides an implementation overview and detailed, step-by-step instructions. The overview should provide enough context for you to complete the implementation if you're already familiar with the AWS Management Console or you want to explore the services and documentation yourself without following a walkthrough. |
| 18 | + |
| 19 | +If you're using the latest version of the Chrome, Firefox, or Safari web browsers the step-by-step instructions won't be visible until you expand the section. |
| 20 | + |
| 21 | +### 1. Associate an API Gateway IAM policy with your Cognito authenticated users' role |
| 22 | + |
| 23 | +#### Background |
| 24 | +For us to be able to use request signing and IAM-based fine-grained access control, we'll first need to associate an IAM policy that provides permissions to invoke API operations for your API Gateway deployment. For further details, you can review [controlling access to an API with IAM permissions](https://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html) documentation. |
| 25 | + |
| 26 | +#### High-Level Instructions |
| 27 | +In the IAM console, assocate the *WildRydesAPI-StandardUserPolicy* with your Cognito Identity Pool's authenticated user role to provide all authenticated users access to invoke operations the */ride* path. |
| 28 | + |
| 29 | +<details> |
| 30 | +<summary><strong>Step-by-step instructions (expand for details)</strong></summary><p> |
| 31 | + |
| 32 | +1. Go the AWS Management Console, click **Services** then select **IAM** under Security, Identity, and Compliance. |
| 33 | + |
| 34 | +1. Choose **Policies**. |
| 35 | + |
| 36 | +1. Search for *WildRydes* to see the *WildRydesAPI-StandardUserPolicy* which was created by the Serverless Backed CloudFormation template. |
| 37 | + |
| 38 | +  |
| 39 | + |
| 40 | +1. Click the **WildRydesAPI-StandardUserPolicy** policy name. |
| 41 | + |
| 42 | +1. Review the policy which was created by CloudFormation to authorize requests to your API Gateway deployment. |
| 43 | + |
| 44 | +  |
| 45 | + > This policy allows access to invoke any method within the /rides path on any stage of API Gatweay. For more details about authoring IAM policies for API Gateway, visit the [controlling access to an API with IAM permissions](https://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html) documentation. |
| 46 | + |
| 47 | +1. Choose **Roles**. |
| 48 | + |
| 49 | +1. Search for *WildRydes* to find the two roles which were created by Cognito Identity Pools when you created the Identity Pool in module one. Should you not be able to find the roles here, you can alternatively go to the **Cognito Federated Identities** console, find the correct identity pool, then click **Edit Identity Pool** in the top-right corner to see the roles listed. Each identity pool has both an Unauthenticated user role and an Authenticated user role. |
| 50 | + |
| 51 | +1. Once you have found the names of the roles, go back to the IAM console and select the *Auth* role for your authenticated users. |
| 52 | + |
| 53 | +1. Choose **Attach policies** to attach |
| 54 | + |
| 55 | +1. Search for `WildRydes` and check the box next to the policy named *WildRydesAPI-StandardUserAccess*. |
| 56 | + |
| 57 | +  |
| 58 | + |
| 59 | +1. Choose **Attach policy**. |
| 60 | + |
| 61 | +1. You should now see the *WildRydesAPI-StandardUserAccess* policy associated with your Cognito IAM auth role. |
| 62 | + |
| 63 | +  |
| 64 | + |
| 65 | +</p></details> |
| 66 | + |
| 67 | + |
| 68 | +### 2. Enable API Gateway authorization with AWS Identity and Access Management (IAM) |
| 69 | + |
| 70 | +#### Background |
| 71 | +In addition to using JSON Web Tokens (JWTs) for authentication, API Gateway can leverage AWS request signing and parse the request signature to determine the requesting user. In this step, you'll update your authorization type to *IAM* for your API which will then use AWS's Identity and Access Management (IAM) capabilities to authorize requests via IAM policies. |
| 72 | + |
| 73 | +#### High-Level Instructions |
| 74 | +In the Amazon API Gateway console, update the authorization type to *AWS_IAM* for the *POST* method on the */ride* resource. Next, re-deploy the API to make your change take effect. |
| 75 | + |
| 76 | +<details> |
| 77 | +<summary><strong>Step-by-step instructions (expand for details)</strong></summary><p> |
| 78 | + |
| 79 | +1. In the AWS Management Console choose **Services** then select **API Gateway** under Security, Identity, and Compliance. |
| 80 | + |
| 81 | +2. Choose the API named *WildRydes*. |
| 82 | + |
| 83 | +3. Browse to **Resources** while within your Wild Rydes API in the API Gateway console. |
| 84 | + |
| 85 | +4. Select the **POST** method under the */ride* resource path. |
| 86 | + |
| 87 | +5. Choose **Method Request** |
| 88 | + |
| 89 | +  |
| 90 | + |
| 91 | +6. Choose the pencil icon next to `Authorization` to edit the setting. |
| 92 | + |
| 93 | +7. Select *AWS_IAM* from the list of authorization options presented. |
| 94 | + |
| 95 | +  |
| 96 | + |
| 97 | +8. **Save** your selection by clicking the checkmark icon next to the drop down. |
| 98 | + |
| 99 | +  |
| 100 | + |
| 101 | +9. Next, choose the **Actions** button at the top of the resources list. |
| 102 | + |
| 103 | +10. Choose **Deploy API** from the list of options presented. |
| 104 | + |
| 105 | +11. For deployment stage, select `prod` then click **Deploy**. |
| 106 | + |
| 107 | +12. You've now successfully deployed your new authentication integration to your API's production environment. |
| 108 | + |
| 109 | +**Configure your Wild Rydes web app to authenticate API requests** |
| 110 | + |
| 111 | +Now that you've deployed the new authorizer configuration to production, all API requests must be authenticated to be processed. |
| 112 | + |
| 113 | +13. Return to your Wild Rydes app, sign in at */signin* if necessary, and attempt to request a ride. |
| 114 | + |
| 115 | +14. You should receive an *Error finding unicorn*. If you open the developer console, you will see that we received a HTTP 401 error, which means it was an unauthorized request. To authenticate our requests properly, we need to send an Authorization header. |
| 116 | + |
| 117 | + > If you at first still that you requests go through without any errors, try requesting a ride again in 30-60 seconds to allow the API Gateway changes to fully propagate. |
| 118 | +
|
| 119 | +15. Go back to Cloud9 and open the */website/src/pages/MainApp.js* files. |
| 120 | + |
| 121 | +16. Update your current *getData* method to the following method, which removes the *Authorization* header and adds debugging information to show us the request signature as requests are sent. The default behavior of the AWS Amplify library is the sign all requests with SigV4 signing when no authorization header is specified, so this will automatically sign all requests using this algorithm without extra development effort. **Save your changes** after making this update. |
| 122 | + |
| 123 | + ``` |
| 124 | + async getData(pin) { |
| 125 | + Amplify.Logger.LOG_LEVEL = 'DEBUG'; |
| 126 | + const apiRequest = { |
| 127 | + body: { |
| 128 | + PickupLocation: { |
| 129 | + Longitude: pin.longitude, |
| 130 | + Latitude: pin.latitude |
| 131 | + } |
| 132 | + }, |
| 133 | + headers: { |
| 134 | + 'Content-Type': 'application/json' |
| 135 | + } |
| 136 | + }; |
| 137 | + logger.info('API Request:', apiRequest); |
| 138 | + return await API.post(apiName, apiPath, apiRequest); |
| 139 | + } |
| 140 | + ``` |
| 141 | +
|
| 142 | +17. Allow the application to refresh, sign-in again, and request a ride. |
| 143 | +
|
| 144 | +18. The unicorn ride request should be fulfilled as before now. To see the full request headers which were sent, look at the developer console for an message which includes the API Request details, including the full signature and headers of the request. |
| 145 | +
|
| 146 | +</p></details> |
| 147 | +<br> |
| 148 | +
|
| 149 | +If the API now invokes correctly and application funcions as expected again, you can move on to the next module, [IAM-based Authorization](../3_IAMAuthorization). |
0 commit comments