Tag Archives: Security Blog

Selecting and migrating a Facebook API version for Amazon Cognito

Post Syndicated from James Li original https://aws.amazon.com/blogs/security/selecting-and-migrating-a-facebook-api-version-for-amazon-cognito/

On May 1, 2020, Facebook will remove version 2.12 of the Facebook Graph API. This change impacts Amazon Cognito customers who are using version 2.12 of the Facebook Graph API in their identity federation configuration. In this post, I explain how to migrate your Amazon Cognito configuration to use the latest version of the Facebook API.

Amazon Cognito provides authentication, authorization, and user management for your web and mobile apps. Your users can sign in directly with a user name and password, or through a third party, such as Facebook, Amazon, Google, or Apple.

An Amazon Cognito User Pool is a user directory that helps you manage identities. It’s also where users can sign into your web or mobile app. User pools support federation through third-party identity providers, such as Google, Facebook, and Apple, as well as Amazon’s own Login with Amazon. Additionally, federation can use identity providers that work with OpenID Connect (OIDC) or Security Assertion Markup Language (SAML) 2.0. Federating a user through the third-party identity provider streamlines the user experience, because users don’t need to sign up directly for your web or mobile app.

Amazon Cognito User Pools now enable users to select the version of the Facebook API for federated login. Previously, version 2.12 of Facebook’s Graph API was automatically used for federated login and to retrieve user attributes from Facebook. By selecting a specific version of Facebook’s API, you can now upgrade versions and test changes. This provides a mechanism to revert back to earlier versions if necessary.

To help ease this transition for our customers, we are doing two phases of mitigation. In the first phase, already underway, you can choose which Facebook version to use for federated login. You can test out the new API version and discover the impact upgrading has on your application. If you must make changes, you can revert to the older version, and you have until May 1, 2020 to perform updates. In the second phase, starting sometime in April, we will automatically migrate customers to version 5.0 if they haven’t selected an API version.

There are benefits to having access to newer versions of Facebook APIs. For instance, if customers who use version 5.0 store a Facebook access token and use it to call the Messenger API, they can use webhook events. This type of benefit is useful for users who react or reply to messages from businesses. You can also use business asset groups to manage a large number of assets with Facebook API v4.0 and the Facebook Marketing API.

How to use different Facebook API versions with Amazon Cognito

These instructions assume you’re familiar with Amazon Cognito User Pools and the User Pool clients. You also need a User Pool domain already set up with the appropriate settings for a hosted UI. If you haven’t set up a user pool yet, you can find the instructions in the Amazon Cognito Developer Guide. You need your User Pool domain information when you set up your Facebook app.

Set up the Facebook app

  1. Go to the Facebook for Developers website and sign in, or sign up if you do not have an account. Create a new Facebook app if you must, or you can reuse an existing one.
  2. Navigate to the App Dashboard and select your App.
  3. On the navigation menu, select Products, then Facebook Login, and then Settings.
  4. In the Valid OAuth Redirect URLs field, add your user pool domain with the endpoint /oauth2/idpresponse. As shown in Figure 1, it should look like https://<yourDomainPrefix>.auth.<region>.amazoncognito.com/oauth2/idpresponse.

    Figure 1

    Figure 1

  5. In the navigation menu, select Settings, then choose Basic.
  6. Note your App ID and your App Secret for the next step.

Adding your Facebook app to your Amazon Cognito user pool

Next, you need to add your Facebook app to your user pool. This can be done either through the AWS Management Console or the command line interface (CLI) and I will show you both methods.

Adding the Facebook app to a user pool through using the AWS Management Console

    1. On the AWS Management Console, navigate to Amazon Cognito, then select Manage Pools. From the list that shows up, select your user pool.
    2. On the navigation menu, select Federation, then Identity Providers.
    3. Select Facebook. Enter the Facebook App ID and App Secret from step 6 above. Then, under Authorize Scopes, enter the appropriate scopes.
    4. In the navigation menu, select Federation and go to Attributes Mapping.
    5. Now select the version of the Facebook API you want to use. By default, the highest available version (v6.0) for newly created Facebook identity providers is pre-selected for you.
    6. After choosing your API version and attribute mapping, click Save.

 

Figure 2

Figure 2

Adding the Facebook app to a user pool through the CLI

The command below adds the Facebook app configuration to your user pool. Use the values for <USER_POOL_ID>,<FACEBOOK_APP_ID> and <FACEBOOK_APP_SECRET> that you noted earlier:


aws cognito-idp create-identity-provider --cli-input-json '{
    "UserPoolId": "<USER_POOL_ID>",
    "ProviderName": "Facebook",
    "ProviderType": "Facebook",
    "ProviderDetails": {
        "client_id": "<FACEBOOK_APP_ID>",
        "client_secret": "<FACEBOOK_APP_SECRET>",
        "authorize_scopes": "email",
        "api_version": "v5.0"
    },
    "AttributeMapping": {
        "email": "email"
    }
}'

The command below updates the Facebook app configuration to your user pool. Use the values for <USER_POOL_ID>, <FACEBOOK_APP_ID> and <FACEBOOK_APP_SECRET> that you noted earlier:


aws cognito-idp update-identity-provider --cli-input-json '{
    "UserPoolId": "<USER_POOL_ID>",
    "ProviderName": "Facebook",
    "ProviderType": "Facebook",
    "ProviderDetails": {
        "client_id": "<FACEBOOK_APP_ID>",
        "client_secret": "<FACEBOOK_APP_SECRET>",
        "authorize_scopes": "email",
        "api_version": "v5.0"
    },
    "AttributeMapping": {
        "email": "email"
    }
}'

You can verify that the create or update was successful by checking the version returned in the describe-identity-provider call:


aws cognito-idp describe-identity-provider --user-pool-id "" --provider-name "Facebook"
{
    "IdentityProvider": {
        "UserPoolId": "<USER_POOL_ID>",
        "ProviderName": "Facebook",
        "ProviderType": "Facebook",
        "ProviderDetails": {
            "api_version": "v5.0",
            "attributes_url": "https://graph.facebook.com/v5.0/me?fields=",
            "attributes_url_add_attributes": "true",
            "authorize_scopes": "email",
            "authorize_url": "https://www.facebook.com/v5.0/dialog/oauth",
            "client_id": "<FACEBOOK_APP_ID>",
            "client_secret": "<FACEBOOK_APP_SECRET>",
            "token_request_method": "GET",
            "token_url": "https://graph.facebook.com/v5.0/oauth/access_token"
        },
        "AttributeMapping": {
            "email": "email",
            "username": "id"
        },
        ...
    }
}

Use the updated configuration with the Cognito Hosted UI:

  1. On the AWS Console for Amazon Cognito, navigate to your user pool and go to the navigation menu. In App Integration, go to App client settings, find your app, and check Facebook as the Enabled Identity Providers.
  2. Select Launch Hosted UI.
  3. Select Continue with Facebook.
  4. If you aren’t automatically signed in at this point, the URL displays your selected version. For example, if v5.0 was selected, the URL starts with: https://www.facebook.com/v5.0/dialog/oauth. If you would like to disable automatic sign-in, simply remove your app from Facebook so that the sign-in prompts for permissions again. Follow these instructions to learn more.
  5. The browser returns to your redirect URL with a code issued by Amazon Cognito if it was successful.

Notes on testing

Facebook will redirect your API call to a more recent version if your app is not allowed to call it. For example, if you created your Facebook app in November 2018, the latest available version at the time was version 3.2. If you were to call the Graph API using version 3.0, the call is upgraded to version 3.2. You can tell which version you are using by referring to the facebook-api-version header in Facebook’s response headers.

If an attribute was not marked as required, and the attribute is missing from Facebook, federation still succeeds, but the attribute is empty in the user pool. There have been various deprecations of fields from Facebook since Facebook federation was launched for Amazon Cognito. For instance, gender and birthday attributes have since changed to be explicitly requested on their own separate permissions rather than granted by default. The cover attribute has also been deprecated. You can confirm that your attribute has successfully federated on the user’s page in the user pools page of the AWS Management Console for Amazon Cognito. You should, as part of your migration, validate that end attributes that you are working with are passed in the way you expect.

Summary

In this post, I explained how to select the version of Facebook’s Graph API for federated login. If you already use Amazon Cognito for federated login with Facebook, you should migrate to the most recent version as soon as possible. Use this process to make sure you get all the attributes you need for your application. New customers can immediately take advantage of the latest API version.

If you have feedback about this blog post, submit comments in the Comments section below. If you have questions about this blog post, start a new thread on the Amazon Cognito Forums or contact AWS Support.

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.

Author

James Li

James is a Software Development Engineer at Amazon Cognito. He values operational excellence and security. James is from Toronto, Canada, where he has worked as a software developer for 4 years.

TLS 1.2 to become the minimum for all AWS FIPS endpoints

Post Syndicated from Janelle Hopper original https://aws.amazon.com/blogs/security/tls-1-2-to-become-the-minimum-for-all-aws-fips-endpoints/

To improve security for data in transit, AWS will update all of our AWS Federal Information Processing Standard (FIPS) endpoints to a minimum Transport Layer Security (TLS) version TLS 1.2 over the next year. This update will deprecate the ability to use TLS 1.0 and TLS 1.1 on all FIPS endpoints across all AWS Regions by March 31, 2021. No other AWS endpoints are affected by this change.

As outlined in the AWS Shared Responsibility Model, security and compliance is a shared responsibility between AWS and our customers. When a customer makes a connection from their client application to an AWS service endpoint, the client provides its TLS minimum and TLS maximum version. The AWS service endpoint selects the maximum version offered.

What should customers do to prepare for this update?

Customers should confirm that their client applications support TLS 1.2 by verifying it is encapsulated between the clients’ minimum and the maximum TLS versions. We encourage customers to be proactive with security standards in order to avoid any impact to availability and to protect the integrity of their data in transit. Also, we recommend configuration changes should be tested in a staging environment, before introduction into production workloads.

When will these changes happen?

To minimize the impact to our customers who use TLS 1.0 and TLS 1.1, AWS is rolling out changes on a service-by-service basis between now and the end of March 2021. For each service, after a 30-day period during which no connections are detected, AWS will deploy a configuration change to remove support for them. After March 31, 2021, AWS may update the endpoint configuration to remove TLS 1.0 and 1.1, even if we detect customer connections. Additional reminders will be provided before these updates are final.

What are AWS FIPS endpoints?

All AWS services offer Transport Layer Security (TLS) 1.2 encrypted endpoints that can be used for all API calls. Some AWS services also offer FIPS 140-2 endpoints for customers that require use of FIPS validated cryptographic libraries.

What is Transport Layer Security (TLS)?

Transport Layer Security (TLS) is a cryptographic protocol designed to provide secure communication across a computer network. API calls to AWS services are secured using TLS.

Is there more assistance available to help verify or update client applications?

Customers using an AWS Software Development Kit (AWS SDK) can find information about how to properly configure their client’s minimum and maximum TLS versions on the following topics in the AWS SDKs:

Or see Tools to Build on AWS, and browse by programming language to find the relevant SDK.

Additionally, AWS IQ enables customers to find, securely collaborate with, and pay AWS Certified third-party experts for on-demand project work. Visit the AWS IQ page for information about how to submit a request, get responses from experts, and choose the expert with the right skills and experience. Log into your console and select Get Started with AWS IQ to start a request.

The AWS Technical Support tiers cover development and production issues for AWS products and services, along with other key stack components. AWS Support does not include code development for client applications.

If you have any questions or issues, please start a new thread on one of the AWS Forums, or contact AWS Support or your Technical Account Manager (TAM). If you have feedback about this post, submit comments in the Comments section below.

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.

Sincerely,
Amazon Web Services

Author

Janelle Hopper

Janelle Hopper is a Senior Technical Program Manager in AWS Security with over 15 years of experience in the IT security field. She works with AWS services, infrastructure, and administrative teams to identify and drive innovative solutions that improve AWS’ security posture.

Use AWS Lambda authorizers with a third-party identity provider to secure Amazon API Gateway REST APIs

Post Syndicated from Bryant Bost original https://aws.amazon.com/blogs/security/use-aws-lambda-authorizers-with-a-third-party-identity-provider-to-secure-amazon-api-gateway-rest-apis/

Note: This post focuses on Amazon API Gateway REST APIs used with OAuth 2.0 and custom AWS Lambda authorizers. API Gateway also offers HTTP APIs, which provide native OAuth 2.0 features. For more information about which is right for your organization, see Choosing Between HTTP APIs and REST APIs.

Amazon API Gateway is a fully managed AWS service that simplifies the process of creating and managing REST APIs at any scale. If you are new to API Gateway, check out Amazon API Gateway Getting Started to get familiar with core concepts and terminology. In this post, I will demonstrate how an organization using a third-party identity provider can use AWS Lambda authorizers to implement a standard token-based authorization scheme for REST APIs that are deployed using API Gateway.

In the context of this post, a third-party identity provider refers to an entity that exists outside of AWS and that creates, manages, and maintains identity information for your organization. This identity provider issues cryptographically signed tokens to users containing information about the user identity and their permissions. In order to use these non-AWS tokens to control access to resources within API Gateway, you will need to define custom authorization code using a Lambda function to “map” token characteristics to API Gateway resources and permissions.

Defining custom authorization code is not the only way to implement authorization in API Gateway and ensure resources can only be accessed by the correct users. In addition to Lambda authorizers, API Gateway offers several “native” options that use existing AWS services to control resource access and do not require any custom code. To learn more about the established practices and authorization mechanisms, see Controlling and Managing Access to a REST API in API Gateway.

Lambda authorizers are a good choice for organizations that use third-party identity providers directly (without federation) to control access to resources in API Gateway, or organizations requiring authorization logic beyond the capabilities offered by “native” authorization mechanisms.

Benefits of using third-party tokens with API Gateway

Using a Lambda authorizer with third-party tokens in API Gateway can provide the following benefits:

  • Integration of third-party identity provider with API Gateway: If your organization has already adopted a third-party identity provider, building a Lambda authorizer allows users to access API Gateway resources by using their third-party credentials without having to configure additional services, such as Amazon Cognito. This can be particularly useful if your organization is using the third-party identity provider for single sign-on (SSO).
  • Minimal impact to client applications: If your organization has an application that is already configured to sign in to a third-party identity provider and issue requests using tokens, then minimal changes will be required to use this solution with API Gateway and a Lambda authorizer. By using credentials from your existing identity provider, you can integrate API Gateway resources into your application in the same manner that non-AWS resources are integrated.
  • Flexibility of authorization logic: Lambda authorizers allow for the additional customization of authorization logic, beyond validation and inspection of tokens.

Solution overview

The following diagram shows the authentication/authorization flow for using third-party tokens in API Gateway:

Figure 1: Example Solution Architecture

Figure 1: Example Solution Architecture

  1. After a successful login, the third-party identity provider issues an access token to a client.
  2. The client issues an HTTP request to API Gateway and includes the access token in the HTTP Authorization header.
  3. The API Gateway resource forwards the token to the Lambda authorizer.
  4. The Lambda authorizer authenticates the token with the third-party identity provider.
  5. The Lambda authorizer executes the authorization logic and creates an identity management policy.
  6. API Gateway evaluates the identity management policy against the API Gateway resource that the user requested and either allows or denies the request. If allowed, API Gateway forwards the user request to the API Gateway resource.

Prerequisites

To build the architecture described in the solution overview, you will need the following:

  • An identity provider: Lambda authorizers can work with any type of identity provider and token format. The post uses a generic OAuth 2.0 identity provider and JSON Web Tokens (JWT).
  • An API Gateway REST API: You will eventually configure this REST API to rely on the Lambda authorizer for access control.
  • A means of retrieving tokens from your identity provider and calling API Gateway resources: This can be a web application, a mobile application, or any application that relies on tokens for accessing API resources.

For the REST API in this example, I use API Gateway with a mock integration. To create this API yourself, you can follow the walkthrough in Create a REST API with a Mock Integration in Amazon API Gateway.

You can use any type of client to retrieve tokens from your identity provider and issue requests to API Gateway, or you can consult the documentation for your identity provider to see if you can retrieve tokens directly and issue requests using a third-party tool such as Postman.

Before you proceed to building the Lambda authorizer, you should be able to retrieve tokens from your identity provider and issue HTTP requests to your API Gateway resource with the token included in the HTTP Authorization header. This post assumes that the identity provider issues OAuth JWT tokens, and the example below shows a raw HTTP request addressed to the mock API Gateway resource with an OAuth JWT access token in the HTTP Authorization header. This request should be sent by the client application that you are using to retrieve your tokens and issue HTTP requests to the mock API Gateway resource.


# Example HTTP Request using a Bearer token\
GET /dev/my-resource/?myParam=myValue HTTP/1.1\
Host: rz8w6b1ik2.execute-api.us-east-1.amazonaws.com\
Authorization: Bearer eyJraWQiOiJ0ekgtb1Z5eEpPSF82UDk3...}

Building a Lambda authorizer

When you configure a Lambda authorizer to serve as the authorization source for an API Gateway resource, the Lambda authorizer is invoked by API Gateway before the resource is called. Check out the Lambda Authorizer Authorization Workflow for more details on how API Gateway invokes and exchanges information with Lambda authorizers. The core functionality of the Lambda authorizer is to generate a well-formed identity management policy that dictates the allowed actions of the user, such as which APIs the user can access. The Lambda authorizer will use information in the third-party token to create the identity management policy based on “permissions mapping” documents that you define — I will discuss these permissions mapping documents in greater detail below.

After the Lambda authorizer generates an identity management policy, the policy is returned to API Gateway and API Gateway uses it to evaluate whether the user is allowed to invoke the requested API. You can optionally configure a setting in API Gateway to automatically cache the identity management policy so that subsequent API invocations with the same token do not invoke the Lambda authorizer, but instead use the identity management policy that was generated on the last invocation.

In this post, you will build your Lambda authorizer to receive an OAuth access token and validate its authenticity with the token issuer, then implement custom authorization logic to use the OAuth scopes present in the token to create an identity management policy that dictates which APIs the user is allowed to access. You will also configure API Gateway to cache the identity management policy that is returned by the Lambda authorizer. These patterns provide the following benefits:

  • Leverage third-party identity management services: Validating the token with the third party allows for consolidated management of services such as token verification, token expiration, and token revocation.
  • Cache to improve performance: Caching the token and identity management policy in API Gateway removes the need to call the Lambda authorizer for each invocation. Caching a policy can improve performance; however, this increased performance comes with addition security considerations. These considerations are discussed below.
  • Limit access with OAuth scopes: Using the scopes present in the access token, along with custom authorization logic, to generate an identity management policy and limit resource access is a familiar OAuth practice and serves as a good example of customizable authentication logic. Refer to Defining Scopes for more information on OAuth scopes and how they are typically used to control resource access.

The Lambda authorizer is invoked with the following object as the event parameter when API Gateway is configured to use a Lambda authorizer with the token event payload; refer to Input to an Amazon API Gateway Lambda Authorizer for more information on the types of payloads that are compatible with Lambda authorizers. Since you are using a token-based authorization scheme, you will use the token event payload. This payload contains the methodArn, which is the Amazon Resource Name (ARN) of the API Gateway resource that the request was addressed to. The payload also contains the authorizationToken, which is the third-party token that the user included with the request.


# Lambda Token Event Payload  
{   
 type: 'TOKEN',  
 methodArn: 'arn:aws:execute-api:us-east-1:2198525...',  
 authorizationToken: 'Bearer eyJraWQiOiJ0ekgt...'  
}

Upon receiving this event, your Lambda authorizer will issue an HTTP POST request to your identity provider to validate the token, and use the scopes present in the third-party token with a permissions mapping document to generate and return an identity management policy that contains the allowed actions of the user within API Gateway. Lambda authorizers can be written in any Lambda-supported language. You can explore some starter code templates on GitHub. The example function in this post uses Node.js 10.x.

The Lambda authorizer code in this post uses a static permissions mapping document. This document is represented by apiPermissions. For a complex or highly dynamic permissions document, this document can be decoupled from the Lambda authorizer and exported to Amazon Simple Storage Service (Amazon S3) or Amazon DynamoDB for simplified management. The static document contains the ARN of the deployed API, the API Gateway stage, the API resource, the HTTP method, and the allowed token scope. The Lambda authorizer then generates an identity management policy by evaluating the scopes present in the third-party token against those present in the document.

The fragment below shows an example permissions mapping. This mapping restricts access by requiring that users issuing HTTP GET requests to the ARN arn:aws:execute-api:us-east-1:219852565112:rz8w6b1ik2 and the my-resource resource in the DEV API Gateway stage are only allowed if they provide a valid token that contains the email scope.


# Example permissions document  
{  
 "arn": "arn:aws:execute-api:us-east-1:219852565112:rz8w6b1ik2",  
 "resource": "my-resource",  
 "stage": "DEV",  
 "httpVerb": "GET",  
 "scope": "email"  
}

The logic to create the identity management policy can be found in the generateIAMPolicy() method of the Lambda function. This method serves as a good general example of the extent of customization possible in Lambda authorizers. While the method in the example relies solely on token scopes, you can also use additional information such as request context, user information, source IP address, user agents, and so on, to generate the returned identity management policy.

Upon invocation, the Lambda authorizer below performs the following procedure:

  1. Receive the token event payload, and isolate the token string (trim “Bearer ” from the token string, if present).
  2. Verify the token with the third-party identity provider.

    Note: This Lambda function does not include this functionality. The method, verifyAccessToken(), will need to be customized based on the identity provider that you are using. This code assumes that the verifyAccessToken() method returns a Promise that resolves to the decoded token in JSON format.

  3. Retrieve the scopes from the decoded token. This code assumes these scopes can be accessed as an array at claims.scp in the decoded token.
  4. Iterate over the scopes present in the token and create identity and access management (IAM) policy statements based on entries in the permissions mapping document that contain the scope in question.
  5. Create a complete, well-formed IAM policy using the generated IAM policy statements. Refer to IAM JSON Policy Elements Reference for more information on programmatically building IAM policies.
  6. Return complete IAM policy to API Gateway.
    
    /*
     * Sample Lambda Authorizer to validate tokens originating from
     * 3rd Party Identity Provider and generate an IAM Policy
     */
    
    const apiPermissions = [
      {
        "arn": "arn:aws:execute-api:us-east-1:219852565112:rz8w6b1ik2", // NOTE: Replace with your API Gateway API ARN
        "resource": "my-resource", // NOTE: Replace with your API Gateway Resource
        "stage": "dev", // NOTE: Replace with your API Gateway Stage
        "httpVerb": "GET",
        "scope": "email"
      }
    ];
    
    var generatePolicyStatement = function (apiName, apiStage, apiVerb, apiResource, action) {
      'use strict';
      // Generate an IAM policy statement
      var statement = {};
      statement.Action = 'execute-api:Invoke';
      statement.Effect = action;
      var methodArn = apiName + "/" + apiStage + "/" + apiVerb + "/" + apiResource + "/";
      statement.Resource = methodArn;
      return statement;
    };
    
    var generatePolicy = function (principalId, policyStatements) {
      'use strict';
      // Generate a fully formed IAM policy
      var authResponse = {};
      authResponse.principalId = principalId;
      var policyDocument = {};
      policyDocument.Version = '2012-10-17';
      policyDocument.Statement = policyStatements;
      authResponse.policyDocument = policyDocument;
      return authResponse;
    };
    
    var verifyAccessToken = function (accessToken) {
      'use strict';
      /*
      * Verify the access token with your Identity Provider here (check if your 
      * Identity Provider provides an SDK).
      *
      * This example assumes this method returns a Promise that resolves to 
      * the decoded token, you may need to modify your code according to how
      * your token is verified and what your Identity Provider returns.
      */
    };
    
    var generateIAMPolicy = function (scopeClaims) {
      'use strict';
      // Declare empty policy statements array
      var policyStatements = [];
      // Iterate over API Permissions
      for ( var i = 0; i  -1 ) {
          // User token has appropriate scope, add API permission to policy statements
          policyStatements.push(generatePolicyStatement(apiPermissions[i].arn, apiPermissions[i].stage, apiPermissions[i].httpVerb,
                                                        apiPermissions[i].resource, "Allow"));
        }
      }
      // Check if no policy statements are generated, if so, create default deny all policy statement
      if (policyStatements.length === 0) {
        var policyStatement = generatePolicyStatement("*", "*", "*", "*", "Deny");
        policyStatements.push(policyStatement);
      }
      return generatePolicy('user', policyStatements);
    };
    
    exports.handler = async function(event, context) {
      // Declare Policy
      var iamPolicy = null;
      // Capture raw token and trim 'Bearer ' string, if present
      var token = event.authorizationToken.replace("Bearer ", "");
      // Validate token
      await verifyAccessToken(token).then(data => {
        // Retrieve token scopes
        var scopeClaims = data.claims.scp;
        // Generate IAM Policy
        iamPolicy = generateIAMPolicy(scopeClaims);
      })
      .catch(err => {
        console.log(err);
        // Generate default deny all policy statement if there is an error
        var policyStatements = [];
        var policyStatement = generatePolicyStatement("*", "*", "*", "*", "Deny");
        policyStatements.push(policyStatement);
        iamPolicy = generatePolicy('user', policyStatements);
      });
      return iamPolicy;
    };  
    

The following is an example of the identity management policy that is returned from your function.


# Example IAM Policy
{
  "principalId": "user",
  "policyDocument": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow",
        "Resource": "arn:aws:execute-api:us-east-1:219852565112:rz8w6b1ik2/get/DEV/my-resource/"
      }
    ]
  }
}

It is important to note that the Lambda authorizer above is not considering the method or resource that the user is requesting. This is because you want to generate a complete identity management policy that contains all the API permissions for the user, instead of a policy that only contains allow/deny for the requested resource. By generating a complete policy, this policy can be cached by API Gateway and used if the user invokes a different API while the policy is still in the cache. Caching the policy can reduce API latency from the user perspective, as well as the total amount of Lambda invocations; however, it can also increase vulnerability to Replay Attacks and acceptance of expired/revoked tokens.

Shorter cache lifetimes introduce more latency to API calls (that is, the Lambda authorizer must be called more frequently), while longer cache lifetimes introduce the possibility of a token expiring or being revoked by the identity provider, but still being used to return a valid identity management policy. For example, the following scenario is possible when caching tokens in API Gateway:

  • Identity provider stamps access token with an expiration date of 12:30.
  • User calls API Gateway with access token at 12:29.
  • Lambda authorizer generates identity management policy and API Gateway caches the token/policy pair for 5 minutes.
  • User calls API Gateway with same access token at 12:32.
  • API Gateway evaluates access against policy that exists in the cache, despite original token being expired.

Since tokens are not re-validated by the Lambda authorizer or API Gateway once they are placed in the API Gateway cache, long cache lifetimes may also increase susceptibility to Replay Attacks. Longer cache lifetimes and large identity management policies can increase the performance of your application, but must be evaluated against the trade-off of increased exposure to certain security vulnerabilities.

Deploying the Lambda authorizer

To deploy your Lambda authorizer, you first need to create and deploy a Lambda deployment package containing your function code and dependencies (if applicable). Lambda authorizer functions behave the same as other Lambda functions in terms of deployment and packaging. For more information on packaging and deploying a Lambda function, see AWS Lambda Deployment Packages in Node.js. For this example, you should name your Lambda function myLambdaAuth and use a Node.js 10.x runtime environment.

After the function is created, add the Lambda authorizer to API Gateway.

  1. Navigate to API Gateway and in the navigation pane, under APIs, select the API you configured earlier
  2. Under your API name, choose Authorizers, then choose Create New Authorizer.
  3. Under Create Authorizer, do the following:
    1. For Name, enter a name for your Lambda authorizer. In this example, the authorizer is named Lambda-Authorizer-Demo.
    2. For Type, select Lambda
    3. For Lambda Function, select the AWS Region you created your function in, then enter the name of the Lambda function you just created.
    4. Leave Lambda Invoke Role empty.
    5. For Lambda Event Payload choose Token.
    6. For Token Source, enter Authorization.
    7. For Token Validation, enter:
      
      ^(Bearer )[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)$
      			

      This represents a regular expression for validating that tokens match JWT format (more below).

    8. For Authorization Caching, select Enabled and enter a time to live (TTL) of 1 second.
  4. Select Save.

 

Figure 2: Create a new Lambda authorizer

Figure 2: Create a new Lambda authorizer

This configuration passes the token event payload mentioned above to your Lambda authorizer, and is necessary since you are using tokens (Token Event Payload) for authentication, rather than request parameters (Request Event Payload). For more information, see Use API Gateway Lambda Authorizers.

In this solution, the token source is the Authorization header of the HTTP request. If you know the expected format of your token, you can include a regular expression in the Token Validation field, which automatically rejects any request that does not match the regular expression. Token validations are not mandatory. This example assumes the token is a JWT.


# Regex matching JWT Bearer Tokens  
^(Bearer )[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)$

Here, you can also configure how long the token/policy pair will be cached in API Gateway. This example enables caching with a TTL of 1 second.

In this solution, you leave the Lambda Invoke Role field empty. This field is used to provide an IAM role that allows API Gateway to execute the Lambda authorizer. If left blank, API Gateway configures a default resource-based policy that allows it to invoke the Lambda authorizer.

The final step is to point your API Gateway resource to your Lambda authorizer. Select the configured API Resource and HTTP method.

  1. Navigate to API Gateway and in the navigation pane, under APIs, select the API you configured earlier.
  2. Select the GET method.

    Figure 3: GET Method Execution

    Figure 3: GET Method Execution

  3. Select Method Request.
  4. Under Settings, edit Authorization and select the authorizer you just configured (in this example, Lambda-Authorizer-Demo).

    Figure 4: Select your API authorizer

    Figure 4: Select your API authorizer

Deploy the API to an API Gateway stage that matches the stage configured in the Lambda authorizer permissions document (apiPermissions variable).

  1. Navigate to API Gateway and in the navigation pane, under APIs, select the API you configured earlier.
  2. Select the / resource of your API.
  3. Select Actions, and under API Actions, select Deploy API.
  4. For Deployment stage, select [New Stage] and for the Stage name, enter dev. Leave Stage description and Deployment description blank.
  5. Select Deploy.

    Figure 5: Deploy your API stage

    Figure 5: Deploy your API stage

Testing the results

With the Lambda authorizer configured as your authorization source, you are now able to access the resource only if you provide a valid token that contains the email scope.

The following example shows how to issue an HTTP request with curl to your API Gateway resource using a valid token that contains the email scope passed in the HTTP Authorization header. Here, you are able to authenticate and receive an appropriate response from API Gateway.


# HTTP Request (including valid token with "email" scope)  
$ curl -X GET \  
> 'https://rz8w6b1ik2.execute-api.us-east-1.amazonaws.com/dev/my-resource/?myParam=myValue' \  
> -H 'Authorization: Bearer eyJraWQiOiJ0ekgtb1Z5eE...'  
  
{  
 "statusCode" : 200,  
 "message" : "Hello from API Gateway!"  
}

The following JSON object represents the decoded JWT payload used in the previous example. The JSON object captures the token scopes in scp, and you can see that the token contained the email scope.

Figure 6: JSON object that contains the email scope

Figure 6: JSON object that contains the email scope

If you provide a token that is expired, is invalid, or that does not contain the email scope, then you are not able to access the resource. The following example shows a request to your API Gateway resource with a valid token that does not contain the email scope. In this example, the Lambda authorizer rejects the request.


# HTTP Request (including token without "email" scope)  
$ curl -X GET \  
> 'https://rz8w6b1ik2.execute-api.us-east-1.amazonaws.com/dev/my-resource/?myParam=myValue' \  
> -H 'Authorization: Bearer eyJraWQiOiJ0ekgtb1Z5eE...'  
  
{  
 "Message" : "User is not authorized to access this resource with an explicit deny"  
}

The following JSON object represents the decoded JWT payload used in the above example; it does not include the email scope.

Figure 7: JSON object that does not contain the email scope

Figure 7: JSON object that does not contain the email scope

If you provide no token, or you provide a token not matching the provided regular expression, then you are immediately rejected by API Gateway without invoking the Lambda authorizer. API Gateway only forwards tokens to the Lambda authorizer that have the HTTP Authorization header and pass the token validation regular expression, if a regular expression was provided. If the request does not pass token validation or does not have an HTTP Authorization header, API Gateway rejects it with a default HTTP 401 response. The following example shows how to issue a request to your API Gateway resource using an invalid token that does match the regular expression you configured on your authorizer. In this example, API Gateway rejects your request automatically without invoking the authorizer.


# HTTP Request (including a token that is not a JWT)  
$ curl -X GET \  
> 'https://rz8w6b1ik2.execute-api.us-east-1.amazonaws.com/dev/my-resource/?myParam=myValue' \  
> -H 'Authorization: Bearer ThisIsNotAJWT'  
  
{  
 "Message" : "Unauthorized"  
}

These examples demonstrate how your Lambda authorizer allows and denies requests based on the token format and the token content.

Conclusion

In this post, you saw how Lambda authorizers can be used with API Gateway to implement a token-based authentication scheme using third-party tokens.

Lambda authorizers can provide a number of benefits:

  • Leverage third-party identity management services directly, without identity federation.
  • Implement custom authorization logic.
  • Cache identity management policies to improve performance of authorization logic (while keeping in mind security implications).
  • Minimally impact existing client applications.

For organizations seeking an alternative to Amazon Cognito User Pools and Amazon Cognito identity pools, Lambda authorizers can provide complete, secure, and flexible authentication and authorization services to resources deployed with Amazon API Gateway. For more information about Lambda authorizers, see API Gateway Lambda Authorizers.

If you have feedback about this post, submit comments in the Comments section below.

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.

Author

Bryant Bost

Bryant Bost is an Application Consultant for AWS Professional Services based out of Washington, DC. As a consultant, he supports customers with architecting, developing, and operating new applications, as well as migrating existing applications to AWS. In addition to web application development, Bryant specializes in serverless and container architectures, and has authored several posts on these topics.

Top 10 security items to improve in your AWS account

Post Syndicated from Nathan Case original https://aws.amazon.com/blogs/security/top-10-security-items-to-improve-in-your-aws-account/

If you’re looking to improve your cloud security, a good place to start is to follow the top 10 most important cloud security tips that Stephen Schmidt, Chief Information Security Officer for AWS, laid out at AWS re:Invent 2019. Below are the tips, expanded to help you take action.

10 most important security tips

1) Accurate account information

When AWS needs to contact you about your AWS account, we use the contact information defined in the AWS Management Console, including the email address used to create the account and those listed under Alternate Contacts. All email addresses should be set up to go to aliases that are not dependent on a single person. You should also have a process for regularly checking that these email addresses work, and that you are responding to emails—especially security notifications you might receive from [email protected]. Learn how to set the alternate contacts to help ensure someone is receiving important messages, even when you are unavailable.

Alternative Contacts user interface

2) Use multi-factor authentication (MFA)

MFA is the best way to protect accounts from inappropriate access. Always set up MFA on your Root user and AWS Identity and Access Management (IAM) users. If you use AWS Single Sign-On (SSO) to control access to AWS or to federate your corporate identity store, you can enforce MFA there. Implementing MFA at the federated identity provider (IdP) means that you can take advantage of existing MFA processes in your organization. To get started, see Using Multi-Factor Authentication (MFA) in AWS.

3) No hard-coding secrets

When you build applications on AWS, you can use AWS IAM roles to deliver temporary, short-lived credentials for calling AWS services. However, some applications require longer-lived credentials, such as database passwords or other API keys. If this is the case, you should never hard code these secrets in the application or store them in source code.

You can use AWS Secrets Manager to control the information in your application. Secrets Manager allows you to rotate, manage, and retrieve database credentials, API keys, and other secrets through their lifecycle. Users and applications can retrieve secrets with a call to Secrets Manager APIs, eliminating the need to hard code sensitive information in plain text.

You should also learn how to use AWS IAM roles for applications running on Amazon EC2. Also, for best results, learn how to securely provide database credentials to AWS Lambda functions by using AWS Secrets Manager.

4) Limit security groups

Security groups are a key way that you can enable network access to resources you have provisioned on AWS. Ensuring that only the required ports are open and the connection is enabled from known network ranges is a foundational approach to security. You can use services such as AWS Config or AWS Firewall Manager to programmatically ensure that the virtual private cloud (VPC) security group configuration is what you intended. The Network Reachability rules package analyzes your Amazon Virtual Private Cloud (Amazon VPC) network configuration to determine whether your Amazon EC2 instances can be reached from external networks, such as the Internet, a virtual private gateway, or AWS Direct Connect. AWS Firewall Manager can also be used to automatically apply AWS WAF rules to internet-facing resources across your AWS accounts. Learn more about detecting and responding to changes in VPC Security Groups.

5) Intentional data policies

Not all data is created equal, which means classifying data properly is crucial to its security. It’s important to accommodate the complex tradeoffs between a strict security posture and a flexible agile environment. A strict security posture, which requires lengthy access-control procedures, creates stronger guarantees about data security. However, such a security posture can work counter to agile and fast-paced development environments, where developers require self-service access to data stores. Design your approach to data classification to meet a broad range of access requirements.

How you classify data doesn’t have to be as binary as public or private. Data comes in various degrees of sensitivity and you might have data that falls in all of the different levels of sensitivity and confidentiality. Design your data security controls with an appropriate mix of preventative and detective controls to match data sensitivity appropriately. In the suggestions below, we deal mostly with the difference between public and private data. If you have no classification policy currently, public versus private is a good place to start.

To protect your data once it has been classified, or while you are classifying it:

  1. If you have Amazon Simple Storage Service (Amazon S3) buckets that are for public usage, move all of that data into a separate AWS account set aside for public access. Set up policies to allow only processes — not humans — to move data into those buckets. This lets you block the ability to make a public Amazon S3 bucket in any other AWS account.
  2. Use Amazon S3 to block public access in any account that should not be able to share data through Amazon S3.
  3. Use two different IAM roles for encryption and decryption with KMS. This lets you separate the data entry (encryption) and data review (decryption), and it allows you to do threat detection on the failed decryption attempts by analyzing that role.

6) Centralize CloudTrail logs

Logging and monitoring are important parts of a robust security plan. Being able to investigate unexpected changes in your environment or perform analysis to iterate on your security posture relies on having access to data. AWS recommends that you write logs, especially AWS CloudTrail, to an S3 bucket in an AWS account designated for logging (Log Archive). The permissions on the bucket should prevent deletion of the logs, and they should also be encrypted at rest. Once the logs are centralized, you can integrate with SIEM solutions or use AWS services to analyze them. Learn how to use AWS services to visualize AWS CloudTrail logs. Once you have CloudTrail logs centralized, you can also use the same Log Archive account to centralize logs from other sources, such as CloudWatch Logs and AWS load balancers.

7) Validate IAM roles

As you operate your AWS accounts to iterate and build capability, you may end up creating multiple IAM roles that you discover later you don’t need. Use AWS IAM Access Analyzer to review access to your internal AWS resources and determine where you have shared access outside your AWS accounts. Routinely reevaluating AWS IAM roles and permissions with Security Hub or open source products such as Prowler will give you the visibility needed to validate compliance with your Governance, Risk, and Compliance (GRC) policies. If you’re already past this point, and have already created multiple roles, you can search for unused IAM roles and remove them.

8) Take actions on findings (This isn’t just GuardDuty anymore!)

AWS Security Hub, Amazon GuardDuty, and AWS Identity and Access Management Access Analyzer are managed AWS services that provide you with actionable findings in your AWS accounts. They are easy to turn on and can integrate across multiple accounts. Turning them on is the first step. You also need to take action when you see findings. The action(s) to take are determined by your own incident response policy. For each finding, ensure that you have determined what your required response actions should be.

Action can be notifying a human to respond, but as you get more experienced in AWS services, you will want to automate the response to the findings generated by Security Hub or GuardDuty. Learn more about how to automate your response and remediation from Security Hub findings.

9) Rotate keys

One of the things that Security Hub provides is a view of the compliance posture of your AWS accounts using the CIS Benchmarks. One of these checks is to look for IAM users with access keys more than 90 days old. If you need to use access keys rather than roles, you should rotate them regularly. Review best practices for managing AWS access keys for more guidance. If your users access AWS via federation, then you can remove the need to issue AWS access keys for your users. Users authenticate to the IdP and assume an IAM role in the target AWS account. The result is that long-term credentials are not needed, and your user will have short-term credentials associated with an IAM role.

10) Be involved in the dev cycle

All of the guidance to this point has been focused on the technology configuration that you can implement. The last piece of advice, “be involved in the dev cycle,” is about people, and can be broadly summarized as “raise the security culture of your organization.” The role of people in all parts of the organization is to help the business launch their solutions securely. As people focused on security, we can guide and educate the rest of our organization to understand what they need to do to raise the bar for security in everything they build. Security is everyone’s job — not just for those folks with it in their job title.

What the security people in every organization can do is to make security easier, by shifting the process to make the easiest and most desirable action one that is almost the most secure. For example, each team should not build their own identity federation or logging solution. We are stronger when we work together, and this applies to securing the cloud as well. The goal is to make security more approachable so that co-workers want to talk to the security team because they know it is the place to get help. For more about creating this type of security team, read Cultivating Security Leadership.

Now that you’ve revisited the top 10 things to make your cloud more secure, make sure you have them set up in your AWS accounts — and go build securely!

If you have feedback about this post, submit comments in the Comments section below.

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.

Nathan Case

Nathan Case

Nathan is a Security Strategist, Geek. He joined AWS in 2016. You can learn more about him here.

15 additional AWS services authorized at DoD Impact Level 6 for the AWS Secret Region

Post Syndicated from Tyler Harding original https://aws.amazon.com/blogs/security/15-additional-aws-services-authorized-dod-impact-level-6-aws-secret-region/

The Defense Information Systems Agency (DISA) has authorized 15 additional AWS services in the AWS Secret Region for production workloads at the Department of Defense (DoD) Impact Level (IL) 6 under the DoD’s Cloud Computing Security Requirements Guide (DoD CC SRG). The authorization at DoD IL 6 allows DoD Mission Owners to process classified and mission-critical workloads for National Security Systems in the AWS Secret Region. The AWS Secret Region was built as part of the Commercial Cloud Services (C2S) contract and is available to the DoD on the AWS GSA IT70 schedule.

The AWS services successfully completed an independent evaluation by members of the Intelligence Community (IC), which confirmed that the AWS services effectively implemented 859 security controls using applicable criteria from NIST SP 800-53 Rev 4, the DoD CC SRG, and the Committee on National Security Systems Instruction No. 1253 at the Moderate Confidentiality, Moderate Integrity, and Moderate Availability impact levels.

The 15 AWS services newly authorized by DISA at IL 6 provide additional choices for DoD Mission Owners to leverage the capabilities of the AWS Cloud in service areas such as compute, storage, database, networking, and security, bringing our total IL 6 authorizations to 26 services as listed below.

Authorized AWS services and features at DoD Impact Level 6

  1. Amazon CloudWatch
  2. Amazon DynamoDB
  3. Amazon Elastic Block Store
  4. Amazon Elastic Compute Cloud (including VM Import/Export)
  5. Amazon EC2 Auto Scaling
  6. Amazon ElastiCache
  7. Amazon Kinesis Data Streams
  8. Amazon Redshift
  9. Amazon Relational Database Service (including MariaDB, MySQL, Oracle, PostgreSQL, and SQL Server)
  10. Amazon S3 Glacier
  11. Amazon Simple Notification Service
  12. Amazon Simple Queue Service
  13. Amazon Simple Storage Service
  14. Amazon Simple Workflow
  15. Amazon Virtual Private Cloud
  16. AWS CloudFormation
  17. AWS CloudTrail
  18. AWS Config
  19. AWS Database Migration Service
  20. AWS Direct Connect
  21. AWS Identity and Access Management
  22. AWS Key Management Service
  23. AWS Snowball
  24. AWS Step Functions
  25. AWS Trusted Advisor
  26. Elastic Load Balancing (Classic and Application Load Balancer)

To learn more about AWS solutions for DoD, please see our AWS solution offerings. Follow the AWS Security Blog for future updates on our Services in Scope by Compliance Program page. If you have feedback about this blog post, let us know in the Comments section below.

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.

Author

Tyler Harding

Tyler Harding is the DoD Compliance Program Manager within AWS Security Assurance. He has over 20 years of experience providing information security solutions to federal civilian, DoD, and intelligence agencies.