Skip to main content

This is the ORIGINAL post. 

Transforming Basic Authentication with CloudFront’s KeyValueStore

On Nov 21, 2023, Amazon CloudFront introduced a game-changing feature called KeyValueStore, significantly simplifying edge computing tasks.

In this blog post, we’ll explore how to use this new feature to streamline our CloudFront functions, making them more efficient and easier to manage.

We’ll use Basic Authentication as a practical example to demonstrate the power and simplicity of KeyValueStore in action.

What is Basic Authentication?

Before we dive into the implementation, let’s briefly explain our use case. Basic authentication is a simple protocol that allows web browsers to provide credentials when making requests.

While it’s not the most secure method for sensitive applications, it’s an excellent example of how CloudFront functions can work with KeyValueStore to manage and validate credentials at the edge.

The Old Way: Hardcoded Values

Previously, when implementing Basic Authentication in CloudFront functions, we often resorted to hardcoding values directly into our code. Let’s look at an example:

function handler(event) {
var authHeaders = event.request.headers.authorization;
// username: admin; password: password
// base64 encoded
var expected = "Basic YWRtaW46cGFzc3dvcmQ=";

if (authHeaders && authHeaders.value === expected) {
return event.request;
}

var response = {
statusCode: 401,
statusDescription: "Unauthorized",
headers: {
"www-authenticate": {
value: 'Basic realm="Enter credentials for the secure site"',
},
},
};

return response;
}

With this approach, although it is functional but it has several drawbacks:

  • Security risks associated with hardcoded credentials
  • Lack of flexibility for updating credentials without redeploying the function
  • Difficulty in managing different credentials for various environments

The New Way: CloudFront KeyValueStore

With the introduction of KeyValueStore, we can now store and retrieve small amounts of data directly within CloudFront. This allows for more dynamic and secure handling of sensitive information like Basic Auth credentials.

Here’s how we can refactor our previous example:

import cf from 'cloudfront';
const kvsId = '<keyValueStore_ID>';
const kvsHandle = cf.kvs(kvsId);

async function handler(event) {

var authHeaders = event.request.headers.authorization;
let username = "" // Default value
let password = "" // Default value
try {
username = await kvsHandle.get('username');
password = await kvsHandle.get('password');
} catch (err) {
console.log(`Kvs key lookup failed for username and password: ${err}`);
return {
statusCode: 500,
statusDescription: "Internal Server Error",
};
}
var credentials = `${username}:${password}`;
var expected = "Basic " + Buffer.from(credentials).toString('base64');
if (authHeaders && authHeaders.value === expected) {
return event.request;
}
var response = {
statusCode: 401,
statusDescription: "Unauthorized",
headers: {
"www-authenticate": {
value: 'Basic realm="Enter credentials for this super secure site"',
},
},
};
return response;
}

How CloudFront Functions Work with KeyValueStore

Let’s break down how this new implementation works:

  • We import the CloudFront module and initialize a KeyValueStore handle with a specific ID.
  • Inside our handler function, we attempt to retrieve the username and password from KeyValueStore.
  • If successful, we construct the expected Basic Auth header using these credentials.
  • We then compare this with the provided authorization header, just as before.
  • The rest of the logic remains similar, returning either the original request or an unauthorized response.

This approach demonstrates how CloudFront functions can seamlessly interact with KeyValueStore to retrieve dynamic data at the edge, enabling more flexible and secure implementations of features like Basic Authentication.

Benefits of Using KeyValueStore for Basic Auth

  • Security: Credentials are no longer hardcoded in the function
  • Flexibility: Easily update credentials without redeploying the function
  • Simplicity: Direct integration with CloudFront functions, no need for external services
  • Performance: Low-latency access to data, as it’s stored directly in CloudFront

Why Not Lambda@Edge with Parameter Store?

While Lambda@Edge with Parameter Store is a powerful combination, it can be OVERKILL for simple tasks like Basic Authentication. Here’s why KeyValueStore is preferable in this scenario:

  • Reduced Complexity: No need to set up and manage a separate Lambda function.
  • Lower Latency: KeyValueStore is integrated directly into CloudFront, eliminating the need for external API calls.
  • Cost-Effective: Avoid additional costs associated with Lambda invocations and data transfer.
  • Simplified Deployment: Update values directly in CloudFront without redeploying Lambda functions.

Conclusion

CloudFront’s KeyValueStore feature offers a streamlined approach to handling dynamic data at the edge. By simplifying our Basic Authentication process and moving away from hardcoded values, we’ve enhanced both the security and flexibility of our CloudFront function.

Reference to read

Finally

Please follow me on Medium if you are interested in Cloud, DevOps, automation, programming, and any tech topics. I would also appreciate it if you could give me a clap.

Your comments are always welcome.

Thanks.

Leave a Reply