Search code examples
javaamazon-web-servicesspring-bootamazon-dynamodbmicroservices

Amazon DynamoDB Exception: The security token included in the request is invalid


I'm encountering an issue while attempting to establish a connection to Amazon DynamoDB through a Spring Boot component using 'aws-java-sdk-dynamodb'.

I'm providing the Access Key and Secret Key, but I'm receiving an exception indicating an invalid security token, even though I'm not passing one.

Here's the exception I'm encountering:

   com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The security token included in the request is invalid. (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: UnrecognizedClientException; Request ID: 3JNS4E8K8PR6MG2VLLH6M152R3VV4KQNSO5AEMVJF66Q9ASUAAJG)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1799) ~[aws-java-sdk-core-1.11.725.jar:na]
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1383) ~[aws-java-sdk-core-1.11.725.jar:na]

I'd like to clarify whether a security token is required to connect to AWS DynamoDB from a Spring Boot component in Java. I have gone through with so many sample codes but didn't find any with Security Token. I'm following the code reference in the repository at: https://github.com/yogsma/betterjavacode/tree/main/dynamodbdemo

Could you please provide references on how to establish a successful connection to DynamoDB from a Spring Boot Java component?


Solution

  • You are using an outdated version of the Java SDK. You should strongly consider moving to AWS SDK for Java V2. V1 is not best practice.

    The Amazon DynamoDB V2 Java API lets you perform service operations using your keys. To do so, ensure you configure your keys properly. See Credential settings retrieval order.

    Here is an example that simply lists your tables. Try this code to make sure it works.

    package com.example.dynamodb;
    
    // snippet-start:[dynamodb.java2.list_tables.import]
    import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
    import software.amazon.awssdk.regions.Region;
    import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
    import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
    import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest;
    import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;
    import java.util.List;
    // snippet-end:[dynamodb.java2.list_tables.import]
    
    /**
     * Before running this Java V2 code example, set up your development environment, including your credentials.
     *
     * For more information, see the following documentation topic:
     *
     * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
     */
    public class ListTables {
    
        public static void main(String[] args) {
    
            System.out.println("Listing your Amazon DynamoDB tables:\n");
            ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
            Region region = Region.US_EAST_1;
            DynamoDbClient ddb = DynamoDbClient.builder()
                   .credentialsProvider(credentialsProvider)
                    .region(region)
                    .build();
            listAllTables(ddb);
            ddb.close();
        }
    
        // snippet-start:[dynamodb.java2.list_tables.main]
        public static void listAllTables(DynamoDbClient ddb){
    
            boolean moreTables = true;
            String lastName = null;
    
            while(moreTables) {
                try {
                    ListTablesResponse response = null;
                    if (lastName == null) {
                        ListTablesRequest request = ListTablesRequest.builder().build();
                        response = ddb.listTables(request);
                    } else {
                        ListTablesRequest request = ListTablesRequest.builder()
                                .exclusiveStartTableName(lastName).build();
                        response = ddb.listTables(request);
                    }
    
                    List<String> tableNames = response.tableNames();
                    if (tableNames.size() > 0) {
                        for (String curName : tableNames) {
                            System.out.format("* %s\n", curName);
                        }
                    } else {
                        System.out.println("No tables found!");
                        System.exit(0);
                    }
    
                    lastName = response.lastEvaluatedTableName();
                    if (lastName == null) {
                        moreTables = false;
                    }
    
                } catch (DynamoDbException e) {
                    System.err.println(e.getMessage());
                    System.exit(1);
                }
            }
            System.out.println("\nDone!");
        }
        // snippet-end:[dynamodb.java2.list_tables.main]
    }
    

    After you get that working, you can try more advanced examples such as:

    Discusses how to develop a Spring Boot application that queries Amazon DynamoDB data. The Spring Boot application uses the AWS SDK for Java (v2) to invoke AWS services and is used by a React application that displays the data. The React application uses Cloudscape.

    See - https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/creating_dynamodb_web_app