I think I must be overlooking something really simple, but I just haven't been able to spot what it is. Any help is greatly appreciated!
Overview
I've been troubleshooting a problem accessing the AWS Cloud Directory service via JavaScript in a browser. I've come up with the simplest API request I can think of (ListDirectories) and it still isn't working.
Code
The SDK file referenced (aws-sdk-2.283.1.min.js) is generated from the AWS JavaScript SDK Builder with only the Cloud Directory service selected.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="aws-sdk-2.283.1.min.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
AWS.config.logger = console;
// instantiate a new Cloud Directory client
// providing: region, access key id, secret access key
const cloudDirectory = new AWS.CloudDirectory({region: 'ap-southeast-2', accessKeyId: 'xxxxxxxxxxxxxxxxxxxx', secretAccessKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' });
// call the list directories API
cloudDirectory.listDirectories()
.promise()
.then((response) => {
console.log('Test of Hardcoded Creds successful');
for (let i = 0, l = response.Directories.length; i < l; i++) {
console.log(response.Directories[i].Name);
}
}).catch((reason) => {
console.log('Test of Hardcoded Creds failed: ' + reason);
});
</script>
</body>
Expected Behaviour
A successful call to the API should result in the message "Test of Hardcoded Creds successful" being displayed in the browser debug window, followed by the name of each Cloud Directory.
Observed Behaviour
The browser calls the https://clouddirectory.ap-southeast-2.amazonaws.com/amazonclouddirectory/2017-01-11/directory/list. This is an HTTP OPTIONS request, i.e. the pre-flight to check CORS. This request fails with an HTTP 403 Forbidden error code.
The response message is:
<MissingAuthenticationTokenException>
<Message>Missing Authentication Token</Message>
</MissingAuthenticationTokenException>
With the following console output repeated:
OPTIONS https://clouddirectory.ap-southeast-2.amazonaws.com/amazonclouddirectory/2017-01-11/directory/list 403 (Forbidden)
handleRequest @ aws-sdk-2.283.1.min.js:5
...
(anonymous) @ test.html:17
test.html:1 Failed to load https://clouddirectory.ap-southeast-2.amazonaws.com/amazonclouddirectory/2017-01-11/directory/list: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403.
And then:
aws-sdk-2.283.1.min.js:2 [AWS clouddirectory undefined 0.416s 3 retries] listDirectories({})
test.html:24 Test of Hardcoded Creds failed: NetworkingError: Network Failure
Conclusions
Looking at the request headers I would expect to see the Authorization header for an AWS Signature v4. I think that this being missing is at the root of the problem. Because I'm using the SDK, and it should perform the signing for me, I am doubtful that this can be the actual problem (otherwise more people than just me would be experiencing this).
Troubleshooting Already Conducted
- Different browsers and using private / incognito modes (to ensure browser plugins are not interfering).
- Tested that the Access Key ID and Secret Access Key can be used via PowerShell to perform the same operation (Get-CDIRDirectories). This works, so the credentials are correct.
- Tested that the parameter names for passing the Access Key ID / Secret Access Key are correct - if I change either of the parameter names then the SDK does not call the API and instead returns a missing credentials message.
- Accessing the page locally (i.e. via opening a file on the local machine) as well as from a hosted location (i.e. http to a public S3 bucket).
There are many questions on StackOverflow similar to this but for accessing S3 or API Gateway. This is not the same problem, as with both S3 and API Gateway it is possible to set the CORS configuration for the service. For CloudDirectory this is not the case to the best of my knowledge.