AWS Developer Blog

Building a serverless developer authentication API in Java using AWS Lambda, Amazon DynamoDB, and Amazon Cognito – Part 3

In parts 1 and 2 of this blog post, we saw how easy it is to get started on Java development for AWS Lambda, and use a microservices architecture to quickly iterate on an AuthenticateUser call that integrates with Amazon Cognito. We set up the AWS Toolkit for Eclipse, used the wizard to create a Java Lambda function, implemented logic for checking a user name/password combination against an Amazon DynamoDB table, and then used the Amazon Cognito Identity Broker to get an OpenID token.

In part 3 of this blog post, we will test our function locally as a JUnit test. Upon successful testing, we will then use the AWS Toolkit for Eclipse to configure and upload the function to Lambda, all from within the development environment. Finally, we will test the function from within the development environment on Lambda.

Expand the tst folder in Package Explorer:

You will see the AWS Toolkit for Eclipse has already created some stubs for you to write your own unit test. Double-click AuthenticateUserTest.java. The test must be implemented in the testAuthenticateUser function. The function creates a dummy Lambda context and a custom event that will be your test data for the testing of your Java Lambda function. Open the TestContext.java file to see a stub that is created to represent a Lambda context. The Context object in Java allows you to interact with the AWS Lambda execution environment through the context parameter. The Context object allows you to access useful information in the Lambda execution environment. For example, you can use the context parameter to determine the CloudWatch log stream associated with the function. For a full list of available context properties in the programming model for Java, see the documentation.

As we mentioned in part 1 of our blog post, our custom object is passed as a LinkedHashMap into our Java Lambda function. Create a test input in the createInput function for a valid input (meaning there is a row in your DynamoDB table User that matches your input).

@BeforeClass
    public static void createInput() throws IOException {
        // TODO: set up your sample input object here.
        input = new LinkedHashMap();
        input.put("userName", "Dhruv");
        input.put("passwordHash","8743b52063cd84097a65d1633f5c74f5");
    } 

Fill in any appropriate values for building the context object and then implement the testAuthenticateUser function as follows:

@Test	
    public void testhandleRequest() {
        AuthenticateUser handler = new AuthenticateUser();
        Context ctx = createContext();

        AuthenticateUserResponse output = (AuthenticateUserResponse)handler.handleRequest(input, ctx);

        // TODO: validate output here if needed.
        if (output.getStatus().equalsIgnoreCase("true")) {
            System.out.println("AuthenticateUser JUnit Test Passed");
        }else{
        	Assert.fail("AuthenticateUser JUnit Test Failed");
        }
    }

Save the file. To run the unit test, right-click AuthenticateUserTest, choose Run As, and then choose JUnit Test. If everything goes well, your test should pass. If not, run the test in Debug mode to see if there are any exceptions. The most common causes for test failures are not setting the right region for your DynamoDB table or not setting the AWS credentials in the AWS Toolkit for Eclipse configuration.

Now that we have successfully tested this function, let’s upload it to Lambda. The AWS Toolkit for Eclipse makes this process very simple. To start the wizard, right-click your Eclipse project, choose Amazon Web Services, and then choose Upload function to AWS Lambda.

 
         

You will now see a page that will allow you to configure your Lambda function. Give your Lambda function the name AuthenticateUser and make sure you choose the region in which you created your DynamoDB table and Amazon Cognito identity pool. Choose Next.

On this page, you will configure your Lambda function. Provide a description for your service. The function handler should already have been selected for you.

You will need to create an IAM role for Lambda execution. Choose Create and type AuthenticateUser-Lambda-Execution-Role. We will need to update this role later so your Lambda function has appropriate access to your DynamoDB table and Amazon Cognito identity pool. You will also need to create or choose an S3 bucket where you will upload your function code. In Advanced Settings, for Memory (MB), type 256. For Timeout(s), type 30. Choose Finish.

Your Lambda function should be created. When the upload is successful, go to the AWS Management Console and navigate to the Lambda dashboard to see your newly created function. Before we execute the function, we need to provide the permissions to the Lambda execution role. Navigate to IAM, choose Roles, and then choose the AuthenticateUser-Lambda-Execution-Role. Make sure the following managed policies are attached.

We need to provide two inline policies for the DynamoDB table and Amazon Cognito. Click Create Role Policy, and then add the following policy document. This will give Lambda access to your identity pool.

The policy document that gives access to the DynamoDB table should look like the following:

Finally, go back to Eclipse, right-click your project name, choose Amazon Web Services, and then choose Run Function on AWS Lambda. Provide your custom JSON input in the format we provided in part 1 of the blog and click Invoke. You should see the result of your Lambda function execution in the Eclipse console: