Adding a bit since I struggled with this and maybe this saves someone the same pain. It has to be custom cookie policy and not canned to support more than 1 directory. For each directory you set 3 cookies (CloudFront-Key-Pair-Id, CloudFront-Policy, CloudFront-Signature). For each directory you will need 3 cookies with same name and different paths (for me it was counterintuitive to set the same cookie name more than once but Ive tested and it works). Another hard part is you have to ensure cloudfront domain matches your domain or you cant pass the cookies you ser. On localhost I use host file to create a fake dns lookup for testing (map 127.0.0.1 to myapp.com and cloudfront has to use some domain like cdn.myapp.com).
<dependencyManagement>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.16.60</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.12.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-cloudfront</artifactId>
</dependency>
@GetMapping("/cloudfront-cookies")
public String getCloudfrontCookies(HttpServletResponse resp) {
String path1 = "/protected/user1/";
String path2 = "/protected/user2/";
setCookies(resp, path1, distributionDomain, "https");
setCookies(resp, path2, distributionDomain, "https");
return "success";
}
protected void setCookies(HttpServletResponse resp, String path, String domain, String proto) {
Date start = new Date(System.currentTimeMillis());
Date expiration = new Date(System.currentTimeMillis()+expirationSeconds*1000);
InputStream is = this.getClass().getResourceAsStream(privateKeyFilePath);
try {
PrivateKey privateKey = RSA.privateKeyFromPKCS8(IOUtils.toByteArray(is));
String url = proto + "://" + domain + path + "*";
CookiesForCustomPolicy cp = CloudFrontCookieSigner.getCookiesForCustomPolicy(
url,
privateKey,
keyPairId,
expiration,
start,
null);
Entry<String,String> kpi = cp.getKeyPairId();
Entry<String,String> pol = cp.getPolicy();
Entry<String,String> sig = cp.getSignature();
resp.addCookie(getCookie(pol.getKey(),pol.getValue(),path,domain));
resp.addCookie(getCookie(sig.getKey(),sig.getValue(),path,domain));
resp.addCookie(getCookie(kpi.getKey(),kpi.getValue(),path,domain));
}catch(Exception e) {
e.printStackTrace();
}
finally {
try {is.close();} catch(IOException ignore) {}
}
}
protected Cookie getCookie(String key, String value, String path, String domain) {
Cookie c = new Cookie(key,value);
c.setPath(path);
return c;
}
Some properties are set via properties files and the certificate I get from filesystem. Follow the aws signed cookie documentation for the rest.