Add Ocapi to a website
Requirements
- Your website needs to be able to make a private HTTP request towards our service to validate the user response. This cannot be done by a pure Javascript frontend nor a static website.
- As OCAPI displays images from public institutions, we need to validate the websites using this service. To include Ocapi in your website, please contact us through our contact form.
Workflow
You can learn more about the Ocapi usage workflow here
API documentation
The OpenAPI documentation is available here.
Setup on your website
Information needed from Teklia
You'll need 4 information from Teklia:
- The API base url to use for requests (it's currently
https://ocapi.teklia.com
) - The Javascript payload URL (it should be something like
https://assets.teklia.com/ocapi/X.Y.Z/ocapi-X.Y.Z.js
) -
The credentials for your account on our backend:
-
a public id that will be used by your users
- a private id that will only be used by your website to validate users
Current releases
Stable versions
- Version 0.4.2 is the new stable version, maintained on
https://ocapi.teklia.com/v2
- Javascript payload
- Integrity key is:
+d6Pio4OPpZPYjbsMRIvD3gBOEgfVDpHCsf3kUJ4x0Kkp2fDc5V0eKm99K+RKqcn
You can use that version with the following tag on your website:
<script type="text/javascript" src="https://assets.teklia.com/ocapi/0.4.2/ocapi-0.4.2.js" integrity="sha384-+d6Pio4OPpZPYjbsMRIvD3gBOEgfVDpHCsf3kUJ4x0Kkp2fDc5V0eKm99K+RKqcn" crossorigin="anonymous"></script>
- Version 0.3.2 is still maintained on
https://ocapi.teklia.com/v1
- Javascript payload
- Integrity key is:
JAI/JIuGPO6SWugsKs3nAWV8y8crq008SfxgJU5oLX1HPqAa08OLEDHeameEzj+t
You can use that version with the following tag on your website:
<script type="text/javascript" src="https://assets.teklia.com/ocapi/0.3.2/ocapi-0.3.2.js" integrity="sha384-JAI/JIuGPO6SWugsKs3nAWV8y8crq008SfxgJU5oLX1HPqAa08OLEDHeameEzj+t" crossorigin="anonymous"></script>
Old Stable versions
- Version 0.3.1
- Javascript payload
- Integrity key is:
2/rlHeJ9ZjwSj+GtTzqopMMJSrkjwZWVmQDQuNzaeoIld+2G7gLBMGoMqOkIb8wj
You can use that version with the following tag on your website:
<script type="text/javascript" src="https://assets.teklia.com/ocapi/0.3.1/ocapi-0.3.1.js" integrity="sha384-2/rlHeJ9ZjwSj+GtTzqopMMJSrkjwZWVmQDQuNzaeoIld+2G7gLBMGoMqOkIb8wj" crossorigin="anonymous"></script>
- Version 0.3.0
- Javascript payload
- Integrity key is:
qGnt9bIFK/YpDlqH7dViACryhf0VZwPd9UE0wlKx+Zhf0F/Jyjx9vQ+H3R4fJuvZ
You can use that version with the following tag on your website:
<script type="text/javascript" src="https://assets.teklia.com/captchan/0.3.0/captchan-0.3.0.js" integrity="sha384-qGnt9bIFK/YpDlqH7dViACryhf0VZwPd9UE0wlKx+Zhf0F/Jyjx9vQ+H3R4fJuvZ" crossorigin="anonymous"></script>
This version does not support audio fallbacks.
Legacy version
- Version 0.2.1
- Javascript payload
- Integrity key is:
YQKwIw45el29YcGdymv07mSNmYnFNQjaVp70nRSuHePFKeuE8OvB7n9ep2Q0LSl2
You can use that version with the following tag on your website:
<script type="text/javascript" src="https://assets.teklia.com/captchan/0.2.1/captchan-0.2.1.js" integrity="sha384-YQKwIw45el29YcGdymv07mSNmYnFNQjaVp70nRSuHePFKeuE8OvB7n9ep2Q0LSl2" crossorigin="anonymous"></script>
This version is compatible with the legacy server
Adding the challenge to a form
Once you've picked a form on your website, you can easily add our captcha:
- Include our Javascript payload on your page, as referenced above in the Current releases section.
- Add a placeholder
<div>
element where you want the challenge to appear on your page
<div
id="ocapi-challenge"
data-ocapi-client="ocapiPublicID"
data-ocapi-base-url="ocapiAPIUrl"
></div>
This element needs the ocapi-challenge
(or captchan-challenge
) identifier, and the provided public id as data-ocapi-client
(or data-captchan-client
) attribute.
The captchan-challenge
identifier and the data-captchan-*
attributes are deprecated.
Below are the IDS and attributes available for each version:
ID | 0.2.1 | 0.3.0 | 0.3.1 | 0.3.2 | 0.4.0+ |
---|---|---|---|---|---|
captchan-challenge |
yes | yes | yes | yes | yes |
ocapi-challenge |
- | - | - | yes | yes |
Attribute | 0.2.1 | 0.3.0 | 0.3.1 | 0.3.2 | 0.4.0+ |
---|---|---|---|---|---|
data-captchan-client |
yes | yes | yes | yes | yes |
data-captchan-base-url |
- | yes | yes | yes | yes |
data-ocapi-client |
- | - | - | yes | yes |
data-ocapi-base-url |
- | - | - | yes | yes |
data-ocapi-game-mode |
- | - | - | - | yes |
The data-ocapi-game-mode
attribute activates the game mode. The user will have to fill in several captchas successively. At the end, the final score is displayed and the player can play again.
Please note that this element must be inside a <form>
to be able to validate the user: an hidden <input>
will be added.
⚠ Never include the private id on that page.
Validated challenge (only for version >= 0.3.2)
Each time a challenge is validated, the ocapi-challenge-validated
event is sent to the document
Javascript reference.
Its detail contains a map including the ID of the validated challenge.
Here is an example of the event detail in json:
{
"challenge_id" : "aChallengeId"
}
And here is an example of a script that receives and uses the event:
<script type="text/javascript">
document.addEventListener(
"ocapi-challenge-validated",
(evt) => {
console.log("Challenge " + evt.detail.challenge_id + " has been validated")
}
)
</script>
Validating a user
Once a user has replied to a challenge from your website, your form will include some fields. Note that the captchan-*
fields are deprecated.
Below are the fields available for each version:
Field available | 0.2.1 | 0.3.0 | 0.3.1 | 0.3.2 | 0.4.0+ |
---|---|---|---|---|---|
captchan-challenge-id |
yes | yes | yes | yes | yes |
captchan-client-id |
- | - | yes | yes | yes |
ocapi-challenge-id |
- | - | - | yes | yes |
ocapi-client-id |
- | - | - | yes | yes |
Your website needs to use the unique challenge identifier (ocapi-challenge-id
or captchan-challenge-id
) in order to make an HTTP GET request on our service:
- method
GET
- path:
/state/<client_id>/<challenge_id>
<client_id>
is your public id<challenge_id>
is the unique id included in your form- header:
Authorization: <JWT>
The request must include a Json Web Token Authorization
header configured as:
- the hashing algorithm is
HS512
(Sha 512) - the signing key is the secret key provided by us
- the payload is a map including a public client id, explain below
Where to find the public client id | 0.2.1 | 0.3.0 | 0.3.1 | 0.3.2 | 0.4.0+ |
---|---|---|---|---|---|
your public id | yes | yes | - | - | yes |
captchan-client-id (included in your form) |
- | - | yes | yes | yes |
ocapi-client-id (included in your form) |
- | - | - | yes | yes |
If you can, use directly your public id. Otherwise prefer the ocapi-*
fields because the captchan-*
fields are deprecated.
Here is the payload in json:
{
"client_id": "aPublicID"
}
This endpoint may give several response code:
- 404 when the requested client in the url is not found
- 403 when the Authorization header is missing or invalid
- 404 when the requested challenge is not found
- 200 when the challenge is available
When the challenge is found, you'll get a really simple JSON response payload with a state
key.
It can either be:
- validated
if the user has correctly replied to the challenge
- rejected
if the user provided an invalid answer. You need to reject the user in that case.
- created
if the user did not answer the question. You need to reject the user in that case.
Demo implementation in PHP
You can view the source code of a demonstration implementation in PHP on https://gitlab.teklia.com/teklia/captchan-demo
<?php
# Configure the service
define("BACKEND_URL", "https://ocapi.teklia.com/v2/");
define("FRONTEND_URL", "https://assets.teklia.com/captchan/X.Y.Z.js");
define("CLIENT_ID", "somePublicID");
define("SECRET_KEY", "someSecretKey");
$display_form = true;
$error = false;
if ($_POST) {
if ($_POST["email"] && $_POST["password"]) {
$challenge_id = $_POST["captchan-challenge-id"];
$client_id = CLIENT_ID;
# ⚠ Replace the previous line by this one **only** if you use a version >= 0.3.1
# $client_id = $_POST["captchan-client-id"];
$api_url = BACKEND_URL."state/".CLIENT_ID."/".$challenge_id;
# Create JWT
$payload = [
"client_id" => $client_id,
];
$authorization = create_jwt($payload, SECRET_KEY);
# Send request
$curl = create_curl($api_url, $authorization);
$data = curl_exec($curl);
# Check response
$data = json_decode($data, true);
if (curl_getinfo($curl , CURLINFO_HTTP_CODE) === 200) {
if ($data["state"] === "validated") {
$display_form = false;
} else {
$error = "Captcha not validated";
}
} else if (curl_getinfo($curl , CURLINFO_HTTP_CODE) === 403) {
$error = "Authorization error";
} else if (curl_getinfo($curl , CURLINFO_HTTP_CODE) === 404) {
$error = "Challenge not found";
} else {
$error = curl_error($curl);
}
if ($error) error_log($error.": ".var_export($data, true));
curl_close($curl);
} else {
$error = "Invalid POST request";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="signin.css">
<title>Ocapi by Teklia</title>
<script type="text/javascript" src="<?= FRONTEND_URL ?>"></script>
<script type="text/javascript">
document.addEventListener("ocapi-challenge-validated", (evt) => { console.log("Challenge " + evt.detail.challenge_id + " has been validated") })
</script>
</head>
<body class="text-center">
<?php if($display_form): ?>
<?php if($error): ?>
<div class="error h4 mb-3 font-weight-normal"><?= $error ?></div>
<?php endif; ?>
<form action="" method="post" class="form-signin">
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<div>
<label class="sr-only" for="email">Email address</label>
<input class="form-control" type="email" id="email" name="email" required placeholder="Email address">
</div>
<div class="field">
<label class="sr-only" for="password">Password</label>
<input class="form-control" type="password" id="password" name="password" required placeholder="Password">
</div>
<div class="captcha">
<!-- The challenge will be displayed here -->
<div
id="ocapi-challenge"
data-ocapi-client="<?= CLIENT_ID ?>"
data-ocapi-base-url="<?= BACKEND_URL ?>"
></div>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
<?php else: ?>
<div class="h3 mb-3 font-weight-normal">Hello <?= $_POST["email"] ?></div>
<?php endif; ?>
</body>
</html>