Akamai CDN Setup - Client Side
Overview
The purpose of the Akamai CDN client side implementation is to inject the Arkose client side scripts into the HTML on a page such as Login or Registration. Once an Arkose challenge is triggered and completed, a POST request is made which will trigger the Akamai EdgeWorker to proxy the Arkose Verify request; found here Akamai CDN Setup - Server Side.
Setup
Prerequisite: An Akamai Property needs to be setup. The details on how to do so can also be found in Akamai CDN Setup - Server Side.
Once an Akamai Property is setup, the HTML for a Login or Registration page will need to be hosted and served via the Akamai Property Origin Server. This can be via an AWS S3 bucket, GCP Bucket, or a custom server. Here is an example HTML file with Arkose client side scripts injected:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Akamai CDN Integration - Verify Proxy Example</title>
<!-- Javascript to inject in the page header -->
<script
src="https://client-api.arkoselabs.com/v2/<YOUR PUBLIC KEY>/api.js"
data-callback="setupEnforcement"
async defer
></script>
<!---->
<style>
form { width: 10em; margin: 1em auto; }
form .formField { margin: 0.5em 0 }
</style>
</head>
<body>
<form action="" method="post" id="submitForm">
<h3>Login</h3>
<div class="formField">
<input type="text" id="username" placeholder="Username" />
</div>
<div>
<input type="password" id="password" placeholder="Password" />
</div>
<div class="formField">
<input type="submit" value="Submit" id="submitButton" />
</div>
<p>Select Token Method</p>
<input type="radio" id="header-token-method" name="token-method" value="header" checked="checked">
<label for="header-token-method">Header</label><br>
<input type="radio" id="cookie-token-method" name="token-method" value="cookie">
<label for="cookie-token-method">Cookie</label><br>
</form>
<!-- Javascript to inject before the closing body tag -->
<script>
var arkoseReady = false; // Flag for checking if CAPI has called onReady
var arkoseComplete = false; // Flag to signify the challenge being completed
var arkoseResetting = false; // Flag to signify when the challenge is being reset
var arkose; // Arkose Enforcement Object
// The following variables can be changed
var arkoseCookieName = 'arkoseToken'; // The name of the cookie that the Arkose token will be stored in
var arkoseErrorCookieName = 'arkoseError'; // The name of the cookie that an Arkose error will be stored in
var arkoseCookieLife = 5 * 60 * 1000; // The length of time that the cookie should be active for, 5 mins is the default
var buttonSelector = '#submitButton'; // The querySelector string used for selecting the required button to protect
var button = document.querySelector(buttonSelector);
setupButton();
/**
* Sets up the events for hijacking the button click
*/
function setupButton() {
if (button) {
arkoseComplete = false;
if (!arkoseReady) {
button.setAttribute('disabled', true);
}
button.addEventListener('click', function (event) {
if (!arkoseReady) {
event.preventDefault();
return;
}
if (!arkoseComplete) {
event.preventDefault();
arkose.run();
return;
}
})
}
}
/**
* Sends a request to an endpoint which triggers the Akamai EdgeWorker to make a proxy call to Arkose Verify.
*/
function proxyVerify(token) {
var tokenMethod = document.querySelector('input[name="token-method"]:checked').value;
var request = new XMLHttpRequest();
// Route to run the Proxy EdgeWorker to call Arkose Verify
request.open("POST", "/proxy-verify");
request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
if (tokenMethod === "header") {
request.setRequestHeader('arkose-token', token);
}
if (tokenMethod === "cookie") {
document.cookie = "arkose-token" + '=' + token + ';expires=' + new Date(Date.now() + 10000).toUTCString() + '; path=/;';
}
var body = JSON.stringify({
username: document.getElementById("username").value,
password: document.getElementById("password").value
});
// Sending the request
request.send(body);
request.onload = function () {
if (request.readyState == 4 && request.status == 200) {
const data = request.response;
console.log('Successfully Verified', data);
}
}
}
/**
* In the case of an error reset the arkose cookie and setup a new cookie that tracks the error
* @param {string} error The error string to set in the error cookie
*/
function handleError(error) {
arkoseComplete = true;
document.cookie = arkoseCookieName + '=;expires=' + new Date(Date.now() + arkoseCookieLife).toUTCString() + '; path=/;';
document.cookie = arkoseErrorCookieName + '=' + error + ';expires=' + new Date(Date.now() + arkoseCookieLife).toUTCString() + '; path=/;';
}
/**
* The callback thats called after the Arkose Labs script has been loaded
* @param {object} myEnforcement The Arkose Labs enforcement object
*/
function setupEnforcement(myEnforcement) {
arkose = myEnforcement;
arkose.setConfig({
onReady: function() {
arkoseReady = true;
if (button) {
button.removeAttribute('disabled');
}
if (arkoseResetting) {
arkoseResetting = false;
arkose.run();
}
document.cookie = arkoseCookieName + '=' + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
document.cookie = arkoseErrorCookieName + '=' + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
},
onCompleted: function(response) {
arkoseComplete = true;
if (response.token){
proxyVerify(response.token);
} else {
handleError('TOKEN_MISSING');
}
},
onError: function(response) {
handleError(response.error ? response.error.error : 'error');
button.removeAttribute('disabled');
button.click();
}
});
}
</script>
<!---->
</body>
</html>
To view our example in Github please visit: Arkose Examples Akamai Client Side.
This example HTML page mimics a Login page and contains two fields: username
and password
. The Token Method
is another input that is used to choose how the Arkose Token
is sent to the Akamai EdgeWorker.
Once a User completes an Arkose Challenge, the onCompleted
callback is triggered, where the proxyVerify
function is called with the Arkose Token
. This function makes a POST request to /proxy-verify
, the route in which triggers the EdgeWorker to proxy the verify call runs. This is tied to the Akamai Property rule here: Rule that sets up proxy call. Depending on which Token Method was selected, the Arkose Token is sent via a Header arkose-token
or a Cookie.
This route /proxy-verify can be anything, as long as the Akamai Property contains a rule to run.
The implementation will have to match between the how the Client Side code (this example) and the Server Side code (Akamai CDN Setup - Server Side) is configured. For example, if the Server Side is configured to read in the Arkose Token via the Header, the Client Side will need to send via Header.
Inject EdgeWorker
The following section details on how to leverage Akamai’s EdgeWorkers to be able to Inject Arkose scripts into a HTML file. The example code can be found here: Inject code example.
View this documentation: Arkose Verify EdgeWorker on how to add EdgeWorkers to an Akamai Property.
Updated about 2 months ago