Signed URLs
Introduction
What are Signed URLs?
A Signed URL is a URL that is generated to provide secure, time-limited access to a cloud storage object. These special URLs are useful for safely providing access to files while controlling who can see or edit them.
Why Use Signed URLs?
Enhanced Control : You can set who can read and write the file, for each Signed URL you generate.
Time Limits: You can make access temporary, reducing the chance of unauthorized sharing in the future.
Easy to Use: Users don't need a separate account with the cloud service to access the file, making it quicker and simpler for them.
1. Enable Authenticated Access
Portal instructions
Navigate to the Buckets page and select the bucket your object is located in.
Select Bucket Settings and click Enable Authenticated CDN access. This step allows you to generate Signed URLs for this bucket.
API instructions
PUT /v1/buckets/<bucket_name>/policy/<policy_name>
User can set bucket access policy. Policy name can either be 'public' or 'authenticated'. Buckets are set to public access policy by default.
In case authenticated policy is set for a bucket all content inside the bucket can be accessed with a signed token passed in the URL.
Request example
curl -H "Authorization: Bearer $ACCESS_TOKEN"
-X PUT https://api-cdn.qencode.com/v1/buckets/$BUCKET_NAME/policy/$POLICY_NAME
Response example
{
"status": "ok"
}
PUT /v1/buckets/<yourBucketName>/policy/authenticated
To change a bucket's access policy from public to private.
PUT /v1/buckets/<yourBucketName>/policy/public
To change a bucket's access policy from private to public.
2. Create a Signed Key
Portal instructions
Navigate to the Signing Keys page in the Content Delivery section.
Click on Create signing key and select Media Storage Bucket from the drop down.
Select your bucket, and click Create signing key to confirm your selection.
Important: Immediately secure the displayed private key. This private key will not be displayed again, and is it archived by our system for security reasons.
API instructions
POST /v1/signing-keys
You can create a signing key and use media storage playback authentication.
Request example
curl -X POST 'https://api-cdn.qencode.com/v1/signing-keys' \
-H 'Authorization: Bearer $ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
--data-raw '{"stream_id": "1f1ab6a3-d867-4787-b882-7f2fb1203634"}'
Response example
{
"signing_key": {
"stream_id": "1f1ab6a3-d867-4787-b882-7f2fb1203634",
"private_key": "-----BEGIN RSA PRIVATE KEY-----
MIIJKgIBAAKCAgEA4DAKSi4F8yQTt1L4N9s9Wt+3hBoHt5KMs14jy37YNnqxaIzJ
...
1c4v1P/wPr2sqepof19dbacmGcxplhHJ4d3BXAdInxYuGrgerShJXy5icFWf8A==
-----END RSA PRIVATE KEY-----
",
"created": "2023-06-12 15:00:40",
"id": "ec25a6a6-b31e-4ac9-af01-711460421c6b",
"name": null
}
}
Important: the private_key attribute is only returned once upon the signing key creation. You won't be able to get it from signing key details afterwards.
GET /v1/signing-keys
You can create a signing key and use media storage playback authentication.
Request example
curl -H "Authorization: Bearer $ACCESS_TOKEN"
-X GET https://api-cdn.qencode.com/v1/signing-keys
Response example
{
"signing_keys": [
{
"created": "2023-06-07 14:17:25",
"id": "e52f59d7-e65c-4036-81c6-0163403a1a88",
"domain_id": "aeac03d6-beb0-4638-a094-fbc35653f931"
},
{
"stream_id": "1f1ab6a3-d867-4787-b882-7f2fb1203634",
"created": "2023-06-12 15:00:40",
"id": "ec25a6a6-b31e-4ac9-af01-711460421c6b",
"name": null
}
]
}
GET /v1/signing-keys
Gets a list of user signing keys.
Request example
curl -H "Authorization: Bearer $ACCESS_TOKEN"
-X GET https://api-cdn.qencode.com/v1/signing-keys
Response example
{
"signing_keys": [
{
"created": "2023-06-07 14:17:25",
"id": "e52f59d7-e65c-4036-81c6-0163403a1a88",
"domain_id": "aeac03d6-beb0-4638-a094-fbc35653f931"
},
{
"stream_id": "1f1ab6a3-d867-4787-b882-7f2fb1203634",
"created": "2023-06-12 15:00:40",
"id": "ec25a6a6-b31e-4ac9-af01-711460421c6b",
"name": null
}
]
}
GET /v1/signing-keys/<signing_key_id>
Gets a signing key information.
Request example
curl -H "Authorization: Bearer $ACCESS_TOKEN"
-X GET https://api-cdn.qencode.com/v1/signing-keys/$SIGNING_KEY_ID
Response example
{
"signing_key": {
"stream_id": "1f1ab6a3-d867-4787-b882-7f2fb1203634",
"created": "2023-06-12 15:00:40",
"id": "ec25a6a6-b31e-4ac9-af01-711460421c6b"
}
}
PUT /v1/signing-keys/<signing_key_id>
Updates the signing key name.
Request example
curl -H "Authorization: Bearer $ACCESS_TOKEN"
-X GET https://api-cdn.qencode.com/v1/domains/$DOMAIN_ID \
-H 'Content-Type: application/json' \
--data-raw '{"name": "My signing key"}'
Response example
{
"signing_key": {
"stream_id": "1f1ab6a3-d867-4787-b882-7f2fb1203634",
"created": "2023-06-12 15:00:40",
"id": "ec25a6a6-b31e-4ac9-af01-711460421c6b",
"name": "My signing key"
}
}
DELETE /v1/signing-keys/<signing_key_id>
Deletes a signing key.
Request example
curl -H "Authorization: Bearer $ACCESS_TOKEN"
-X DELETE https://api-cdn.qencode.com/v1/signing-keys/$SIGNING_KEY_ID
Response example
{
"status": "ok"
}
3. Generate signed tokens
Signed tokens are JSON Web Tokens (JWT) used to authenticate requests to Qencode Content delivery service. You can use it to authenticate access to your Qencode media storage bucket.
To authenticate the request a signed token should be added to the resource url using the auth query string param.
To authenticate a request to Qencode media storage bucket you can build a URL like this:
https://$BUCKET.media-storage.$REGION.qencode.com/path/to/video.mp4?auth=$TOKEN
where $BUCKET is your media storage bucket name and $REGION is Qencode media storage region. Currently available Qencode media storage regions are us-west and eu-central.
To authenticate a request to Qencode media storage bucket using the custom domain you can build a URL like this:
https://$CUSTOM_DOMAIN/path/to/video.mp4?auth=$TOKEN
Signed token structure
Once you save, the private key will be displayed, and a caution message will be visible instructing you to safely copy and save the Private Key for future uses. Please note, this key is shown only once.
The structure of a signed token includes a list of headers and payload values. Please see the list of supported headers and payload values below. You can also add your custom payload values to a JWT.
Generate JWT signed token using RS256 algorithm with the following structure:
headers: {
"kid": "<signing key id>",
"alg": "RS256",
"typ": "JWT",
}
payload: {
"uri": "<key_path>",
"exp": "<expiration time>",
"nbf": "<not_before time>"
}
"kid": "<signing key id>" is a mandatory key, contains the key identifier.
"alg": "RS256" - token signing method. Should be set to 'RS256'
"typ": "JWT" - signed token type. Should be set to 'JWT'
"uri": "<s3_key_path>" - is an optional key. Contains directory or full path to the file with access granted using this token. Setting uri to an empty string authorizes the request to access any resource in the bucket.
"exp": "<expiration time>" is an optional key. Contains expiry timestamp after which the token is considered invalid. If this key is missing, the token validity is unlimited.
"nbf": "<not_before time>" is an optional key. Contains start timestamp before which the token is considered invalid. If this key is missing, the token activation time is unlimited.
Code samples in different programming languages you can use to generate a signed token.Recommended Practices:
Periodically set expiration dates for JWT tokens.
Cycle keys on a regular basis.
Maintain unique keys for distinct JWT tokens.
Safeguard both JWT and public keys.
Limitations to Remember:
Private Key Access: Once dispensed, the system doesn't retain the private key.
One Key per Bucket: You can't utilize a single signing key across multiple buckets.
Need Assistance? For a more in-depth understanding, consult the Qencode Documentation or contact Qencode Support at support@qencode.com.