Skip to content

Commit dde854f

Browse files
authored
Merge pull request #77 from prasoon0909/fix/rm-authentication-url-logic
Fix/rm authentication url logic
2 parents 0ac3953 + 8e40b10 commit dde854f

File tree

12 files changed

+218
-276
lines changed

12 files changed

+218
-276
lines changed

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ Javascript SDK for [ImageKit](https://imagekit.io/) provides URL generation for
1414

1515
ImageKit is complete media storage, optimization, and transformation solution that comes with an [image and video CDN](https://imagekit.io/features/imagekit-infrastructure). It can be integrated with your existing infrastructure - storage like AWS S3, web servers, your CDN, and custom domain names, allowing you to deliver optimized images in minutes with minimal code changes.
1616

17+
## Changelog - SDK Version 2.0.0
18+
### Breaking changes
19+
**1. Authentication Process Update:**
20+
* Previously, when using client side file upload, the SDK required the `publicKey` and `authenticationEndpoint` parameters during SDK initialization to fetch security parameters (`signature`, `token`, and `expire`).
21+
* In version 2.0.0, we've updated the authentication process for the SDK. As a user of the SDK, you are now responsible for generating the security parameters (`signature`, `token`, and `expire`) yourself. This means you no longer need to provide the `authenticationEndpoint`. When using the SDK's upload method, make sure to pass these security parameters explicitly along with other [upload options](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload). For guidance on generating these security parameters, please refer to the documentation available [here](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload).
22+
1723
## Installation
1824

1925
### Using npm
@@ -59,12 +65,11 @@ var imagekit = new ImageKit({
5965
});
6066
```
6167

62-
`publicKey` and `authenticationEndpoint` parameters are required if you want to use the SDK for client-side file upload. You can get these parameters from the developer section in your ImageKit dashboard - https://imagekit.io/dashboard#developers
68+
`publicKey` parameter is required if you want to use the SDK for client-side file upload. You can get this parameter from the developer section in your ImageKit dashboard - https://imagekit.io/dashboard#developers
6369
```
6470
var imagekit = new ImageKit({
6571
publicKey: "your_public_api_key",
6672
urlEndpoint: "https://ik.imagekit.io/your_imagekit_id",
67-
authenticationEndpoint: "http://www.yourserver.com/auth",
6873
});
6974
```
7075

@@ -261,9 +266,7 @@ The SDK provides a simple interface using the `.upload()` method to upload files
261266

262267
The `upload()` method requires mandatory `file` and the `fileName` parameter. In addition, it accepts all the parameters supported by the [ImageKit Upload API](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload).
263268

264-
Also, ensure that you have specified `authenticationEndpoint` during SDK initialization. The SDK makes an HTTP GET request to this endpoint and expects a JSON response with three fields, i.e. `signature`, `token`, and `expire`. In addition, the SDK adds a query parameter `t` with a random value to ensure that the request URL is unique and the response is not cached in [Safari iOS](https://github.com/imagekit-developer/imagekit-javascript/issues/59). Your backend can ignore this query parameter.
265-
266-
[Learn how to implement authenticationEndpoint](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload#how-to-implement-authenticationendpoint-endpoint) on your server.
269+
Also before making an upload request, please ensure you have generated mandatory security parameters: `signature`, `token`, and `expire`. To generate these security parameters, refer to the [documentation here](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload). Obtain the parameters using a secure method and pass them, along with the mandatory `file` and `fileName` parameters, to the `upload()` method.
267270

268271
You can pass other parameters supported by the ImageKit upload API using the same parameter name as specified in the upload API documentation. For example, to specify tags for a file at the time of upload, use the `tags` parameter as specified in the [documentation here](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload).
269272

@@ -277,13 +280,12 @@ You can pass other parameters supported by the ImageKit upload API using the sam
277280
<script type="text/javascript" src="../dist/imagekit.js"></script>
278281

279282
<script>
280-
/* SDK initilization
281-
authenticationEndpoint should be implemented on your server. Learn more here - https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload#how-to-implement-authenticationendpoint-endpoint
283+
/*
284+
SDK initilization
282285
*/
283286
var imagekit = new ImageKit({
284287
publicKey: "your_public_api_key",
285288
urlEndpoint: "https://ik.imagekit.io/your_imagekit_id",
286-
authenticationEndpoint: "http://www.yourserver.com/auth"
287289
});
288290
289291
// Upload function internally uses the ImageKit.io javascript SDK
@@ -295,6 +297,9 @@ You can pass other parameters supported by the ImageKit upload API using the sam
295297
file: file.files[0],
296298
fileName: "abc1.jpg",
297299
tags: ["tag1"],
300+
token: 'generated_token',
301+
signature: 'generated_signature',
302+
expire: 'generated_expire',
298303
extensions: [
299304
{
300305
name: "aws-auto-tagging",
@@ -311,6 +316,9 @@ You can pass other parameters supported by the ImageKit upload API using the sam
311316
file: file.files[0],
312317
fileName: "abc1.jpg",
313318
tags: ["tag1"],
319+
token: 'generated_token',
320+
signature: 'generated_signature',
321+
expire: 'generated_expire',
314322
extensions: [
315323
{
316324
name: "aws-auto-tagging",
@@ -352,6 +360,9 @@ imagekit.upload({
352360
file: file.files[0],
353361
fileName: "abc1.jpg",
354362
tags: ["tag1"],
363+
token: 'generated_token',
364+
signature: 'generated_signature',
365+
expire: 'generated_expire',
355366
extensions: [
356367
{
357368
name: "aws-auto-tagging",
@@ -375,6 +386,9 @@ var response = await imagekit.upload({
375386
file: file.files[0],
376387
fileName: "abc1.jpg",
377388
tags: ["tag1"],
389+
token: 'generated_token',
390+
signature: 'generated_signature',
391+
expire: 'generated_expire',
378392
extensions: [
379393
{
380394
name: "aws-auto-tagging",
@@ -394,6 +408,9 @@ try {
394408
file: file.files[0],
395409
fileName: "abc1.jpg",
396410
tags: ["tag1"],
411+
token: 'generated_token',
412+
signature: 'generated_signature',
413+
expire: 'generated_expire',
397414
extensions: [
398415
{
399416
name: "aws-auto-tagging",
@@ -407,4 +424,5 @@ try {
407424

408425
// {'content-type': 'application/json', 'x-request-id': 'ee560df4-d44f-455e-a48e-29dfda49aec5'}
409426
console.log(response.$ResponseMetadata.headers);
410-
}
427+
}
428+
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "imagekit-javascript",
3-
"version": "1.5.5",
3+
"version": "2.0.0",
44
"description": "Javascript SDK for using ImageKit.io in the browser",
55
"main": "dist/imagekit.cjs.js",
66
"module": "dist/imagekit.esm.js",

samples/sample-app/server/server.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ const router = express.Router();
33
const cors = require('cors');
44
const ImageKit = require('imagekit');
55
const uuid = require('uuid');
6-
const fs = require('fs');
76
const path = require('path');
87

98
const pugTemplatePath = path.join(__dirname, "../views/index.pug");
@@ -21,7 +20,6 @@ const startServer = (port = 3000, PUBLIC_KEY, PRIVATE_KEY, URL_ENDPOINT) => {
2120
urlEndpoint: URL_ENDPOINT
2221
});
2322

24-
2523
router.get("/auth", (req, res) => {
2624
try {
2725
const token = req.query.token || uuid.v4();

samples/sample-app/views/index.pug

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ html
2424
var imagekit = new ImageKit({
2525
publicKey: "!{publicKey}",
2626
urlEndpoint: "!{urlEndpoint}",
27-
authenticationEndpoint: "!{authenticationEndpoint}"
2827
});
2928

3029
window.imagekit = imagekit;
@@ -34,6 +33,7 @@ html
3433
e.preventDefault();
3534
var file = document.getElementById("file1");
3635
var fileSize = file.files[0].size;
36+
var AUTH_INVALID_RESPONSE = "Invalid response from authenticationEndpoint. The SDK expects a JSON response with three fields i.e. signature, token and expire."
3737
var statusEl = document.getElementById("status");
3838
statusEl.innerHTML = "Uploading...";
3939

@@ -50,41 +50,72 @@ html
5050
}
5151
});
5252

53-
imagekit.upload({
54-
xhr: customXHR, // Use this if you want to track upload progress
55-
file : file.files[0],
56-
fileName : file.files[0].name || "test_image.jpg",
57-
tags : ["test_tag_1"],
58-
//- extensions: [
59-
//- {
60-
//- name: "aws-auto-tagging",
61-
//- minConfidence: 80,
62-
//- maxTags: 10
63-
//- }
64-
//- ],
65-
}, function(err, result) {
66-
if (err) {
67-
statusEl.innerHTML = "Error uploading image. "+ err.message;
68-
console.log(err)
69-
} else {
70-
statusEl.innerHTML = "File Uploaded";
71-
var sampleTransformations = [{ HEIGHT: 300, WIDTH: 400}];
72-
srcUrl = result.url;
73-
transformedURL = imagekit.url({
74-
src: srcUrl,
75-
transformation : sampleTransformations
76-
});
53+
// Generating security parameters using authenticationEndpoint
54+
const securityParametersRequest = new XMLHttpRequest();
55+
securityParametersRequest.timeout = 60000;
56+
var urlObj = new URL("!{authenticationEndpoint}");
57+
securityParametersRequest.open('GET', urlObj.toString());
58+
securityParametersRequest.ontimeout = function (e) {
59+
console.log(e.message);
60+
return statusEl.innerHTML = "Timeout generating security parameters. "+ e.message
61+
};
62+
securityParametersRequest.onerror = function (e) {
63+
console.log(e.message)
64+
return statusEl.innerHTML = "Request to authenticationEndpoint failed due to network error."+ e.message
65+
}
66+
securityParametersRequest.onload = () => {
67+
if(securityParametersRequest.status === 200) {
68+
var securityParametersObj = JSON.parse(securityParametersRequest.response)
69+
70+
if(!securityParametersObj || !securityParametersObj.token || !securityParametersObj.signature || !securityParametersObj.expire) {
71+
return statusEl.innerHTML = AUTH_INVALID_RESPONSE;
72+
}
73+
74+
// Uploading image
75+
imagekit.upload({
76+
xhr: customXHR, // Use this if you want to track upload progress
77+
file : file.files[0],
78+
fileName : file.files[0].name || "test_image.jpg",
79+
tags : ["test_tag_1"],
80+
token: securityParametersObj.token,
81+
signature: securityParametersObj.signature,
82+
expire: securityParametersObj.expire,
83+
//- extensions: [
84+
//- {
85+
//- name: "aws-auto-tagging",
86+
//- minConfidence: 80,
87+
//- maxTags: 10
88+
//- }
89+
//- ],
90+
}, function(err, result) {
91+
if (err) {
92+
statusEl.innerHTML = "Error uploading image. "+ err.message;
93+
console.log(err)
94+
} else {
95+
statusEl.innerHTML = "File Uploaded";
96+
var sampleTransformations = [{ HEIGHT: 300, WIDTH: 400}];
97+
srcUrl = result.url;
98+
transformedURL = imagekit.url({
99+
src: srcUrl,
100+
transformation : sampleTransformations
101+
});
77102

78-
var orig_img = document.querySelector("#orig_image > p > img");
79-
var trans_img = document.querySelector("#trans_image > p > img");
103+
var orig_img = document.querySelector("#orig_image > p > img");
104+
var trans_img = document.querySelector("#trans_image > p > img");
80105

81-
orig_img.setAttribute("src", srcUrl);
82-
trans_img.setAttribute("src", transformedURL);
106+
orig_img.setAttribute("src", srcUrl);
107+
trans_img.setAttribute("src", transformedURL);
83108

84-
var el = document.getElementById('images')
85-
el.setAttribute("style", "");
109+
var el = document.getElementById('images')
110+
el.setAttribute("style", "");
111+
}
112+
});
113+
} else {
114+
return statusEl.innerHTML = AUTH_INVALID_RESPONSE;
86115
}
87-
});
116+
}
117+
118+
securityParametersRequest.send();
88119
}
89120
} catch(ex) {
90121
console.log(ex);

src/constants/errorMessages.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ export default {
1515
help: "",
1616
},
1717
INVALID_UPLOAD_OPTIONS: { message: "Invalid uploadOptions parameter", help: "" },
18+
MISSING_SIGNATURE: { message: "Missing signature for upload. The SDK expects token, sginature and expire for authentication.", help: ""},
19+
MISSING_TOKEN: { message: "Missing token for upload. The SDK expects token, sginature and expire for authentication.", help: ""},
20+
MISSING_EXPIRE: { message: "Missing expire for upload. The SDK expects token, sginature and expire for authentication.", help: ""},
1821
};

src/interfaces/ImageKitOptions.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@ export interface ImageKitOptions {
44
urlEndpoint: string;
55
sdkVersion?: string;
66
publicKey?: string;
7-
authenticationEndpoint?: string;
87
transformationPosition?: TransformationPosition;
9-
}
8+
}

src/interfaces/UploadOptions.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ export interface UploadOptions {
1313
* Pass the full URL, for example - https://www.example.com/rest-of-the-image-path.jpg.
1414
*/
1515
file: string | Blob | File;
16+
/**
17+
* HMAC-SHA1 digest of the token+expire using your ImageKit.io private API key as a key. This should be in lowercase.
18+
* Warning: Signature must be calculated on the server-side. This field is required for authentication when uploading a file from the client-side.
19+
*/
20+
signature: string;
21+
/**
22+
* A unique value generated by the client, which will be used by the ImageKit.io server to recognize and prevent subsequent retries for the same request. We suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions.
23+
* Note: Sending a value that has been used in the past will result in a validation error. Even if your previous request resulted in an error, you should always send a new value for this field.
24+
*/
25+
token: string;
26+
/**
27+
* The time until your signature is valid. It must be a Unix time in less than 1 hour into the future. It should be in seconds.
28+
*/
29+
expire: number;
1630
/**
1731
* The name with which the file has to be uploaded.
1832
* The file name can contain:

src/upload/index.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,40 @@ export const upload = (
1919
return;
2020
}
2121

22-
if (!options.authenticationEndpoint) {
23-
respond(true, errorMessages.MISSING_AUTHENTICATION_ENDPOINT, callback);
24-
return;
25-
}
26-
2722
if (!options.publicKey) {
2823
respond(true, errorMessages.MISSING_PUBLIC_KEY, callback);
2924
return;
3025
}
3126

27+
if(!uploadOptions.token) {
28+
respond(true, errorMessages.MISSING_TOKEN, callback)
29+
return
30+
}
31+
32+
if(!uploadOptions.signature) {
33+
respond(true, errorMessages.MISSING_SIGNATURE, callback)
34+
return
35+
}
36+
37+
if(!uploadOptions.expire) {
38+
respond(true, errorMessages.MISSING_EXPIRE, callback)
39+
return
40+
}
41+
3242
var formData = new FormData();
3343
let key: keyof typeof uploadOptions;
3444
for (key in uploadOptions) {
3545
if (key) {
3646
if (key === "file" && typeof uploadOptions.file != "string") {
3747
formData.append('file', uploadOptions.file, String(uploadOptions.fileName));
3848
} else if (key === "tags" && Array.isArray(uploadOptions.tags)) {
39-
formData.append('tags', uploadOptions.tags.join(","));
49+
formData.append('tags', uploadOptions.tags.join(","));
50+
} else if (key === 'signature') {
51+
formData.append("signature", uploadOptions.signature);
52+
} else if (key === 'expire') {
53+
formData.append("expire", String(uploadOptions.expire));
54+
} else if (key === 'token') {
55+
formData.append("token", uploadOptions.token);
4056
} else if (key === "responseFields" && Array.isArray(uploadOptions.responseFields)) {
4157
formData.append('responseFields', uploadOptions.responseFields.join(","));
4258
} else if (key === "extensions" && Array.isArray(uploadOptions.extensions)) {
@@ -52,5 +68,5 @@ export const upload = (
5268

5369
formData.append("publicKey", options.publicKey);
5470

55-
request(xhr, formData, { ...options, authenticationEndpoint: options.authenticationEndpoint }, callback);
71+
request(xhr, formData, callback);
5672
};

0 commit comments

Comments
 (0)