Often time course participants will receive their certificate of accomplishment digitally and they can link the image of the certificate in their professional social network like LinkedIn.
Offering digital certificate can add value to your business or course
If you are running these courses, you should highly consider giving out digital certificate to your users. There are few things you need to consider to handle this process.
First, generating the certificate image itself. Then, most importantly ensuring certificate authenticity. Since the image can be doctored digitally, you need to employ your own system to handle certificate validation.
If you think that this is too complicate to handle, it is. Fortunately, you're in the right place.
Secure signed URL can help solve these issues and you'll see how this is handled. Of course, in some complicated cases you would still need to roll your own system but for the majority of the time this is sufficient.
How to
Design your certificate template
A good certificate design should be simple and show all the relevant course information and user's achievement.
AWS-like certificate is a good sample of a concise certificate
Creating Signed URL for Image
1. Getting the necessary information
You'll need some information that can be retrieved from Console > Integrations > Secure Signed Image
Information required in the next step
2. Generate signed URL
The section Basic explains how the URL is generated. You can use the Python code provided and modify it based on the information we need. You also need to specify the proper modifications that will be sent to our API.
For example this is the Python code you can use with the certificate template that was created from previous step.
PYTHON
import json
import hmac
import hashlib
import base64
def base64_encode(string):
"""
Removes any `=` used as padding from the encoded string.
"""
encoded = base64.b64encode(string.encode())
encoded = encoded.rstrip(b'=')
return encoded
def generate_url():
user_id = "be6a052e-bce8-4c14-8bbb-ea6b6f9941d5"
secret_key = "secretzzzz"
base_id = "TEafv3AfNptmzii4zj2jkc"
modifications = [
{ "name": "text_candidate", "text": "John Wick" }
]
# ensure no spaces in json output
encoded = json.dumps(modifications, separators=(',', ':'))
encoded = base64_encode(encoded).decode()
parameters = "{user_id}+{base_id}+{modifications}".format(user_id=user_id, base_id=base_id, modifications=encoded)
signature = hmac.new(secret_key.encode(), parameters.encode(), hashlib.sha256).hexdigest()
url = "https://images.usestencil.com/signed-images/{user_id}/{base_id}.png?modifications={modifications}&s={signature}".format(
base_id=base_id,
user_id=user_id,
modifications=encoded,
signature=signature
)
print(url)
if __name__ == "__main__":
generate_url()
Running the above code, should give you a similar url like
https://images.usestencil.com/signed-images/be6a052e-bce8-4c14-8bbb-ea6b6f9941d5
/TEafv3AfNptmzii4zj2jkc.png?modifications=W3sibmFtZSI6InRleHRfY2FuZGlkYXRlIiwidGV4dCI6IkpvaG4gV2ljayJ9XQ
&s=f69736c6f17cea118a45dc018103694cbde78d89513de977c2fa1c55faf697df
Result
Visiting the URL gives us the certificate,
Signed image with your user's name
Determining authenticity
All certificates generated and hot-linked using our CDN can be considered as authentic i.e. all links started with https://images.usestencil.com/signed-images/...
are authentic.
Why?
All images are signed with your secret key. Trying to modify the data will invalidate the signature.
Continue reading to know the details.
Let's break it down. The URL can be broken down to several parts,
https://images.usestencil.com/signed-images/be6a052e-bce8-4c14-8bbb-ea6b6f9941d5/TEafv3AfNptmzii4zj2jkc.png
This is the base URL
modifications=W3sibmFtZSI6InRleHRfY2FuZGlkYXRlIiwidGV4dCI6IkpvaG4gV2ljayJ9XQ
Base64 encoded modifications
s=f69736c6f17cea118a45dc018103694cbde78d89513de977c2fa1c55faf697df
Signature that we use to determine the authenticity of the request
If we decode the base64 modifications, we will get the following output,
PYTHON
[{"name":"text_candidate","text":"John Wick"}]
You might think, "Hey what if I modify the value and encode it back. That should work, right?"
Let's do that. We changed the value to John the Impostor
and got back the following base64 encoded string.
PYTHON
[{"name":"text_candidate","text":"John the Impostor"}]
W3sibmFtZSI6InRleHRfY2FuZGlkYXRlIiwidGV4dCI6IkpvaG4gdGhlIEltcG9zdG9yIn1d
Putting everything together we get back,
https://images.usestencil.com/signed-images/be6a052e-bce8-4c14-8bbb-ea6b6f9941d5
/TEafv3AfNptmzii4zj2jkc.png
?modifications=W3sibmFtZSI6InRleHRfY2FuZGlkYXRlIiwidGV4dCI6IkpvaG4gdGhlIEltcG9zdG9yIn1d
&s=f69736c6f17cea118a45dc018103694cbde78d89513de977c2fa1c55faf697df`
Visiting the URL gave us the following image instead,
Invalid image
If you look at the response header, you should see the following header x-stencil-error: Invalid signature
The reason is that, the signature doesn't contain the right modifications and thus rejected by our server. By ensuring the image is signed with our secret key, we can ensure image authenticity. Simple, right?
Further integration
As you can see, we have to run one Python script to generate the link for our certificate. There are few things we can do so that we don't have to run the Python script each time. Here are few options you can explore to do this.
1. AWS Lambda
You can modify the Python script as a lambda function that accepts the candidate's name and when run, it will return the generated URL.
You can then combine this with other tools such as Airtable where you can input list of names, and use any automation services like Zapier, Integromat, UiPath and others to run the lambda function when your Airtable rows are added/updated and update the corresponding rows with the generated link.
We have created a guide utilizing AWS Lambda for this. You can find it here
2. Airtable
Airtable has scripting ability and you can write a similar script to generate the link.
3. Google Sheet
Google Sheet also has scripting ability and you can write a similar script to generate the link.
There are numerous of ways to do this and these are just some of them.