AWS Developer Tools Blog
Amazon CloudFront Signed URLs and Cookies are now supported in AWS SDK for Java 2.x
We are pleased to announce the general availability of Amazon CloudFront signed URLs and signed cookies in the AWS SDK for Java 2.x. You can now securely serve private content through CloudFront, requiring that your users access your content by using special CloudFront signed URLs or signed cookies. To configure your CloudFront distribution to use this feature, you must specify a trusted key group (recommended) or AWS account as a trusted signer. For more information on setting up and configuring a CloudFront distribution, please see the Developer Guide.
The new SDK 2.x CloudFrontUtilities
component provides the highly-requested signing features that many customers miss from the AWS SDK for Java 1.x. The new APIs in the SDK 2.x APIs have been redesigned with one point of entry for a streamlined usage experience.
Motivation
You can control access to your content with either signed URLs or signed cookies. Signed URLs allow you to create a new URL that has temporary access to one of your protected CloudFront resources. Signed cookies allow you to create a temporary set of credentials that can be used by your customers to directly access one or many protected CloudFront resources.
Using CloudFront Signing
1) Add a dependency for CloudFront
The first step to getting started is to add the dependency for CloudFront in your project.
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>cloudfront</artifactId>
<version>2.18.26</version> <!-- Update to use the latest version. -->
</dependency>
We recommend using the most recent version of the SDK.
2) Instantiate the CloudFrontUtilities Class
To instantiate the utility class, you just need to call create()
.
import software.amazon.awssdk.services.cloudfront.CloudFrontUtilities;
CloudFrontUtilities cloudFrontUtilities = CloudFrontUtilities.create();
3) Create an CloudFrontSignerRequest
Next, you create a CloudFrontSignerRequest
using a builder. A request can be used for both URLs and cookies.
Example #1: Signed Request with Canned Policy
For a URL/cookie with a canned policy, create a CannedSignerRequest
, specifying the resource URL, private key, public key ID, and expiration date.
import software.amazon.awssdk.services.cloudfront.model.CannedSignerRequest;
import java.security.PrivateKey;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
Instant expirationDate = Instant.now().plus(7, ChronoUnit.DAYS);
String resourceUrl = "https://d1npcfkc2mojrf.cloudfront.net/s3ObjectKey";
String keyPairId = "myKeyPairId";
PrivateKey privateKey = myPrivateKey; // Either PrivateKey or Path can be passed in
CannedSignerRequest cannedRequest = CannedSignerRequest.builder()
.resourceUrl(resourceUrl)
.privateKey(privateKey)
.keyPairId(keyPairId)
.expirationDate(expirationDate)
.build();
Example #2: Signed Request with Custom Policy
For a URL/cookie with a custom policy, create a CustomSignerRequest
, where you can additionally specify the active date and/or the IP range. In this example, we specify both the active date and IP range, though you can choose to specify only one of them.
import software.amazon.awssdk.services.cloudfront.model.CustomSignerRequest;
import java.nio.file.Path;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
Instant expirationDate = Instant.now().plus(7, ChronoUnit.DAYS);
String resourceUrl = "https://d111111abcdef8.cloudfront.net/s3ObjectKey";
String keyPairId = "myKeyPairId";
Instant activeDate = Instant.now().plus(2, ChronoUnit.DAYS);
String ipRange = "192.168.0.1/24";
Path keyFile = myKeyFile; // Either PrivateKey or Path can be passed in
CustomSignerRequest customRequest = CustomSignerRequest.builder()
.resourceUrl(resourceUrl)
.privateKey(keyFile)
.keyPairId(keyPairId)
.expirationDate(expirationDate)
.activeDate(activeDate) //optional
.ipRange(ipRange) //optional
.build();
4) Create a Signed URL/Signed Cookie
After you generate the request, create the signed URL or signed cookie, from which you can optionally generate an SdkHttpRequest
to be executed by an HTTP client.
Example #1: Signed URL with Canned Policy
To create a SignedUrl
with a canned policy, you just need to call getSignedUrlWithCannedPolicy()
, passing in the CannedSignerRequest
instance. With the SignedUrl
object, you can then call url()
to return a signed URL String
.
import software.amazon.awssdk.services.cloudfront.model.CannedSignerRequest;
import software.amazon.awssdk.services.cloudfront.url.SignedUrl;
SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCannedPolicy(cannedRequest);
// Returns a signed URL String that you can provide to users which will allow them to access your content
String url = signedUrl.url()
Example #2: Signed Cookie with Custom Policy
To create a CookiesForCustomPolicy
, you just need to call getCookiesForCustomPolicy()
, passing in the CustomSignerRequest
instance. With the CookiesForCustomPolicy
object, you can call the appropriate methods to return the policy, signature, and key-pair ID cookie header values, which you can then send to the viewer to grant access to your private content.
import software.amazon.awssdk.services.cloudfront.cookie.CookiesForCustomPolicy;
import software.amazon.awssdk.services.cloudfront.model.CustomSignerRequest;
CookiesForCustomPolicy cookies = cloudFrontUtilities.getCookiesForCustomPolicy(customRequest);
// Generates Set-Cookie header values to send to the viewer to allow access
String signatureHeaderValue = cookies.signatureHeaderValue();
String keyPairIdHeaderValue = cookies.keyPairIdHeaderValue();
String policyHeaderValue = cookies.policyHeaderValue();
Cleanup
The CloudFront signed URLs/cookies you generated will be valid until the specified expiration dates, after which users will not be able to access your private content. If you wish to revoke access before the expiration date, you just need to remove the trusted signer from the CloudFront distribution.
To completely tear-down and clean up all your resources, you must first disable your CloudFront distribution. Then, you can delete your distribution, key group, and public key in CloudFront. Finally, you can empty and delete your S3 bucket.
Conclusion
In this blog post we went over the basic functionalities of CloudFront signed URLs and signed cookies. We also showed code examples of a signed URL with a canned policy and a signed cookie with a custom policy. To learn more about how to set up and begin using the feature, visit our Developer Guide. If you are curious about how it is implemented, check out the source code on GitHub. As always, we welcome bug reports, feature requests, and pull requests on the aws-sdk-java-v2 GitHub repository.