@tapni/auth 1.0.5 → 1.0.6-3.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +2 -0
  2. package/dist/.vite/manifest.json +16 -43
  3. package/dist/.well-known/assetlinks.json +10 -12
  4. package/dist/.well-known/microsoft-identity-association.json +5 -5
  5. package/dist/{Apps-DMds3Dv-.js → Apps-XNA4_3B4.js} +34 -34
  6. package/dist/Billing-Br0-fHed.js +256 -0
  7. package/dist/CustomApp-CrlbYDOm.js +83 -0
  8. package/dist/QR-Bvqb60-E.js +41 -0
  9. package/dist/TapniAuth.es.js +1 -1
  10. package/dist/TapniAuth.umd.js +49 -23
  11. package/dist/{install-L-cxSovH.js → install-7FOVy8Ol.js} +6267 -4743
  12. package/dist/site.webmanifest +11 -1
  13. package/dist/style.css +1 -1
  14. package/dist/{web-IFGkBi0t.js → web-UrTMimK1.js} +2 -2
  15. package/package.json +65 -55
  16. package/src/.prettierrc.json +16 -0
  17. package/src/App.vue +326 -269
  18. package/src/eslint.config.js +15 -0
  19. package/src/index.js +4 -0
  20. package/src/install.js +9 -10
  21. package/src/main.js +54 -57
  22. package/src/mixins/apple.mixin.js +56 -54
  23. package/src/mixins/auth.mixin.js +3 -2
  24. package/src/mixins/global.mixin.js +3 -3
  25. package/src/mixins/google.mixin.js +53 -54
  26. package/src/mixins/microsoft.mixin.js +2 -5
  27. package/src/mixins/okta.mixin.js +1 -1
  28. package/src/mixins/qr-auth.mixin.js +111 -107
  29. package/src/mixins/saml.mixin.js +82 -45
  30. package/src/router/index.js +6 -6
  31. package/src/routes.js +1 -1
  32. package/src/services/Api.js +56 -58
  33. package/src/services/AuthService.js +7 -9
  34. package/src/services/CompanyService.js +10 -10
  35. package/src/services/DeviceService.js +3 -3
  36. package/src/services/UserService.js +48 -45
  37. package/src/services/UtilService.js +317 -225
  38. package/src/store/auth.js +485 -549
  39. package/src/store/constants.js +2 -2
  40. package/src/store/event-bus.js +22 -22
  41. package/src/store/locales/cn.js +476 -458
  42. package/src/store/locales/de.js +478 -517
  43. package/src/store/locales/en.js +454 -513
  44. package/src/store/locales/es.js +477 -524
  45. package/src/store/locales/fr.js +477 -516
  46. package/src/store/locales/it.js +477 -514
  47. package/src/store/locales/ja.js +488 -0
  48. package/src/store/locales/kr.js +477 -491
  49. package/src/store/locales/lang.js +51 -43
  50. package/src/store/locales/pt.js +488 -0
  51. package/src/store/locales/sr.js +477 -492
  52. package/src/store/locales/tr.js +477 -487
  53. package/src/store/store.js +6 -6
  54. package/src/views/Account.vue +36 -8
  55. package/src/views/Billing.vue +464 -34
  56. package/src/views/Callback.vue +36 -33
  57. package/src/views/General.vue +151 -185
  58. package/src/views/Login.vue +2 -25
  59. package/src/views/Register.vue +2 -12
  60. package/src/views/Reset.vue +132 -135
  61. package/src/views/Security.vue +13 -7
  62. package/src/views/Verify.vue +153 -151
  63. package/src/views/Welcome.vue +85 -71
  64. package/dist/Account-Cuz87g_8.js +0 -153
  65. package/dist/Billing-BXlQEuNy.js +0 -113
  66. package/dist/CustomApp-CLCMXmMO.js +0 -83
  67. package/dist/General-dW73bMoR.js +0 -479
  68. package/dist/QR-D6ZGcPM0.js +0 -41
  69. package/dist/index.css +0 -193
  70. package/dist/web-AXRKjAOB.js +0 -92
  71. package/src/components/DELETE_Language.vue +0 -168
  72. package/src/components/DELETE_LinkIcon.vue +0 -288
  73. package/src/components/DELETE_ModalOverlay.vue +0 -68
  74. package/src/components/DELETE_OTP.vue +0 -105
  75. package/src/components/DELETE_SSO.vue +0 -120
  76. package/src/components/DELETE_SSOPick.vue +0 -166
  77. package/src/mixins/DELETE_mfa-auth.mixin.js +0 -53
  78. package/src/mixins/facebook.mixin.js +0 -78
@@ -1,49 +1,52 @@
1
1
  import api from './Api.js';
2
2
 
3
3
  export default {
4
- getMe() {
5
- return api().get(`/users/me`);
6
- },
7
- getByUsername(data) {
8
- let referrer = document.referrer || "";
9
- let params = data.utmParams || {};
10
- if (data.dontTap) params.dontTap = true;
11
- return api().get(`/users/${data.username}`, {
12
- params,
13
- headers: { "X-Referer": referrer },
14
- });
15
- },
16
- getByNumber(data) {
17
- let referrer = document.referrer || "";
18
- let params = data.utmParams || {};
19
- if (data.dontTap) params.dontTap = true;
20
- return api().get(`/users/tag/${data.serial}`, {
21
- params,
22
- headers: { "X-Referer": referrer },
23
- });
24
- },
25
- save(data) {
26
- return api().put(`/users`, data);
27
- },
28
- newPassword(data) {
29
- return api().put(`/users/new-password`, data);
30
- },
31
- connect(data) {
32
- return api().post(`/users/connect`, data);
33
- },
34
- eventLog(data) {
35
- return api().post(`/users/log`, data);
36
- },
37
- deleteAccount(data) {
38
- return api().post(`/users/profile/delete`, data);
39
- },
40
- registerDevice(data) {
41
- return api().post(`/users/device/register`, data);
42
- },
43
- addFcmToken(data) {
44
- return api().post(`/users/device/fcm`, data);
45
- },
46
- loginUsingQR(data) {
47
- return api().post("/users/qr/login", data);
48
- }
4
+ getMe() {
5
+ return api().get(`/users/me`);
6
+ },
7
+ getByUsername(data) {
8
+ let referrer = document.referrer || '';
9
+ let params = data.utmParams || {};
10
+ if (data.dontTap) params.dontTap = true;
11
+ return api().get(`/users/${data.username}`, {
12
+ params,
13
+ headers: { 'X-Referer': referrer }
14
+ });
15
+ },
16
+ getByNumber(data) {
17
+ let referrer = document.referrer || '';
18
+ let params = data.utmParams || {};
19
+ if (data.dontTap) params.dontTap = true;
20
+ return api().get(`/users/tag/${data.serial}`, {
21
+ params,
22
+ headers: { 'X-Referer': referrer }
23
+ });
24
+ },
25
+ save(data) {
26
+ return api().put(`/users`, data);
27
+ },
28
+ newPassword(data) {
29
+ return api().put(`/users/new-password`, data);
30
+ },
31
+ connect(data) {
32
+ return api().post(`/users/connect`, data);
33
+ },
34
+ eventLog(data) {
35
+ return api().post(`/users/log`, data);
36
+ },
37
+ deleteAccount(data) {
38
+ return api().post(`/users/profile/delete`, data);
39
+ },
40
+ registerDevice(data) {
41
+ return api().post(`/users/device/register`, data);
42
+ },
43
+ addFcmToken(data) {
44
+ return api().post(`/users/device/fcm`, data);
45
+ },
46
+ loginUsingQR(data) {
47
+ return api().post('/users/qr/login', data);
48
+ },
49
+ updateAccount(data) {
50
+ return api().put('/accounts/me', data);
51
+ }
49
52
  };
@@ -1,228 +1,320 @@
1
- import enLocale from '../store/locales/en';
2
- import deLocale from '../store/locales/de';
3
- import esLocale from '../store/locales/es';
4
- import krLocale from '../store/locales/kr';
5
- import itLocale from '../store/locales/it';
6
- import frLocale from '../store/locales/fr';
7
- import srLocale from '../store/locales/sr';
1
+ import enLocale from '../store/locales/en.js';
2
+ import deLocale from '../store/locales/de.js';
3
+ import esLocale from '../store/locales/es.js';
4
+ import krLocale from '../store/locales/kr.js';
5
+ import itLocale from '../store/locales/it.js';
6
+ import frLocale from '../store/locales/fr.js';
7
+ import srLocale from '../store/locales/sr.js';
8
8
  import trLocale from '../store/locales/tr';
9
+ import { sha256 } from 'js-sha256';
10
+
11
+ // Helper function to safely get random values
12
+ const getRandomValues = (array) => {
13
+ try {
14
+ return window.crypto.getRandomValues(array);
15
+ } catch (e) {
16
+ for (let i = 0; i < array.length; i++) {
17
+ array[i] = Math.floor(Math.random() * 256);
18
+ }
19
+ return array;
20
+ }
21
+ };
22
+
23
+ // Helper function to safely perform crypto digest
24
+ const performDigest = async (data) => {
25
+ try {
26
+ return await window.crypto.subtle.digest('SHA-256', data);
27
+ } catch (e) {
28
+ const hash = sha256(data);
29
+ return new Uint8Array(hash.match(/.{1,2}/g).map(byte => parseInt(byte, 16))).buffer;
30
+ }
31
+ };
32
+
33
+ // Helper function to safely perform crypto encrypt
34
+ const performEncrypt = async (algorithm, key, data) => {
35
+ try {
36
+ return await window.crypto.subtle.encrypt(algorithm, key, data);
37
+ } catch (e) {
38
+ throw new Error('Encryption not supported in this environment');
39
+ }
40
+ };
41
+
42
+ // Helper function to safely perform crypto decrypt
43
+ const performDecrypt = async (algorithm, key, data) => {
44
+ try {
45
+ return await window.crypto.subtle.decrypt(algorithm, key, data);
46
+ } catch (e) {
47
+ throw new Error('Decryption not supported in this environment');
48
+ }
49
+ };
9
50
 
10
51
  export default {
11
- getFirstBrowserLanguage() {
12
- let nav = window.navigator
13
- let browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage']
14
- let i
15
- let language
16
-
17
- // support for HTML 5.1 "navigator.languages"
18
- if (Array.isArray(nav.languages)) {
19
- for (i = 0; i < nav.languages.length; i++) {
20
- language = nav.languages[i]
21
- if (language && language.length) {
22
- return language.slice(0, 2)
23
- }
24
- }
25
- }
26
-
27
- // support for other well known properties in browsers
28
- for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
29
- language = nav[browserLanguagePropertyKeys[i]]
30
- if (language && language.length) {
31
- return language.slice(0, 2)
32
- }
33
- }
34
-
35
- return null
36
- },
37
- compareLangKeys() {
38
- const en = Object.keys(enLocale.default.state);
39
- const de = Object.keys(deLocale.default.state);
40
- const es = Object.keys(esLocale.default.state);
41
- const kr = Object.keys(krLocale.default.state);
42
- const it = Object.keys(itLocale.default.state);
43
- const fr = Object.keys(frLocale.default.state);
44
- const sr = Object.keys(srLocale.default.state);
45
- const tr = Object.keys(trLocale.default.state);
46
-
47
-
48
- // Compare en and de
49
- console.log('In en but not in de', en.filter(x => !de.includes(x)));
50
- console.log('In de but not in en', de.filter(x => !en.includes(x)));
51
- console.log();
52
-
53
- // Compare en and es
54
- console.log('In en but not in es', en.filter(x => !es.includes(x)));
55
- console.log('In es but not in en', es.filter(x => !en.includes(x)));
56
- console.log();
57
-
58
- // Compare en and kr
59
- console.log('In en but not in kr', en.filter(x => !kr.includes(x)));
60
- console.log('In kr but not in en', kr.filter(x => !en.includes(x)));
61
- console.log();
62
-
63
- // Compare en and it
64
- console.log('In en but not in it', en.filter(x => !it.includes(x)));
65
- console.log('In it but not in en', it.filter(x => !en.includes(x)));
66
- console.log();
67
-
68
- // Compare en and fr
69
- console.log('In en but not in fr', en.filter(x => !fr.includes(x)));
70
- console.log('In fr but not in en', fr.filter(x => !en.includes(x)));
71
- console.log();
72
-
73
- // Compare en and sr
74
- console.log('In en but not in sr', en.filter(x => !sr.includes(x)));
75
- console.log('In sr but not in en', sr.filter(x => !en.includes(x)));
76
- console.log();
77
-
78
- // Compare en and tr
79
- console.log('In en but not in tr', en.filter(x => !tr.includes(x)));
80
- console.log('In tr but not in en', tr.filter(x => !en.includes(x)));
81
- console.log();
82
- },
83
- base64ImageToBlob(base64Image) {
84
- // Split into two parts
85
- const parts = base64Image.split(';base64,');
86
-
87
- // Hold the content type
88
- const imageType = parts[0].split(':')[1];
89
-
90
- // Decode Base64 string
91
- const decodedData = window.atob(parts[1]);
92
-
93
- // Create UNIT8ARRAY of size same as row data length
94
- const uInt8Array = new Uint8Array(decodedData.length);
95
-
96
- // Insert all character code into uInt8Array
97
- for (let i = 0; i < decodedData.length; ++i) {
98
- uInt8Array[i] = decodedData.charCodeAt(i);
99
- }
100
-
101
- // Return BLOB image after conversion
102
- return new Blob([uInt8Array], {type: imageType});
103
- },
104
- blobToBase64(blob) {
105
- const reader = new FileReader();
106
- reader.readAsDataURL(blob);
107
- return new Promise(resolve => {
108
- reader.onloadend = () => {
109
- resolve(reader.result);
110
- };
111
- });
112
- },
113
- base64toFile(base64, filename) {
114
-
115
- var arr = base64.split(','),
116
- mime = arr[0].match(/:(.*?);/)[1],
117
- bstr = atob(arr[1]),
118
- n = bstr.length,
119
- u8arr = new Uint8Array(n);
120
-
121
- while (n--) {
122
- u8arr[n] = bstr.charCodeAt(n);
123
- }
124
-
125
- return new File([u8arr], filename, {type: mime});
126
- },
127
- fileToBase64(file) {
128
- new Promise((resolve, reject) => {
129
- const reader = new FileReader();
130
- reader.readAsDataURL(file);
131
- reader.onload = () => resolve(reader.result);
132
- reader.onerror = error => reject(error);
133
- });
134
- },
135
- getUTMParams(data) {
136
- let utm = {}
137
- if (data.utm_source) utm.utm_source = data.utm_source;
138
- if (data.utm_medium) utm.utm_medium = data.utm_medium;
139
- if (data.utm_campaign) utm.utm_campaign = data.utm_campaign;
140
- if (data.utm_term) utm.utm_term = data.utm_term;
141
- if (data.utm_content) utm.utm_content = data.utm_content;
142
- return utm;
143
- },
144
-
145
- cropCardScan(base64PictureData, callback) {
146
-
147
- // image will contain ORIGINAL image
148
- const image = new window.Image();
149
-
150
- // image will contain CROPPED image
151
- const canvas = document.createElement('canvas');
152
- const ctx = canvas.getContext('2d');
153
-
154
- // Load original image into image element
155
- image.src = 'data:image/jpeg;base64,' + base64PictureData;
156
- image.onload = () => {
157
- const sw = image.width;
158
- const sh = image.width / 1.65;
159
- const sx = 0;
160
- const sy = (image.height / 2) - (sh / 2)
161
- const dw = sw;
162
- const dh = sh;
163
- canvas.width = dw;
164
- canvas.height = dh
165
- // https://i.stack.imgur.com/USDAX.png
166
- ctx.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh); // Crop interpolated rectangle
167
- const croppedBase64Image = canvas.toDataURL();
168
-
169
- callback(croppedBase64Image);
170
-
171
- return croppedBase64Image;
172
- };
173
- },
174
- generateRandomString(length) {
175
- let array = new Uint32Array(length);
176
- window.crypto.getRandomValues(array);
177
- return Array.from(array, dec => ('0' + dec.toString(16)).substr(-2)).join('');
178
- },
179
- async pkceChallengeFromVerifier(v) {
180
- const encoder = new TextEncoder();
181
- const data = encoder.encode(v);
182
- const hashed = await window.crypto.subtle.digest('SHA-256', data);
183
- // base64 url encode
184
- return btoa(String.fromCharCode.apply(null, new Uint8Array(hashed))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
185
- },
186
- encryptAES(key, iv, data) {
187
- let encoder = new TextEncoder();
188
- let encoded = encoder.encode(data, storage);
189
- return window.crypto.subtle.encrypt(
190
- {
191
- name: "AES-CBC",
192
- iv: iv,
193
- },
194
- key,
195
- encoded,
196
- );
197
- },
198
- async decryptAES(key, iv, data) {
199
- try {
200
- const fromBase64 = base64String => Uint8Array.from(atob(base64String), c => c.charCodeAt(0));
201
-
202
- data = data.replace(/ /g, '+');
203
-
204
- const encoder = new TextEncoder();
205
- const decoder = new TextDecoder();
206
-
207
- key = encoder.encode(key);
208
- iv = encoder.encode(iv);
209
- data = fromBase64(data, storage);
210
-
211
-
212
- const secretKey = await window.crypto.subtle.importKey('raw', key, 'AES-CBC', true, ['encrypt', 'decrypt']);
213
-
214
-
215
- let decoded = await window.crypto.subtle.decrypt({name: "AES-CBC", iv}, secretKey, data);
216
-
217
- decoded = decoder.decode(decoded);
218
- decoded = decoded.replace(/ /g, '+');
219
- decoded = atob(decoded);
220
-
221
- return decoded;
222
-
223
-
224
- } catch (err) {
225
- console.log(err)
226
- }
227
- }
228
- }
52
+ getFirstBrowserLanguage() {
53
+ let nav = window.navigator;
54
+ let browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];
55
+ let i;
56
+ let language;
57
+
58
+ // support for HTML 5.1 "navigator.languages"
59
+ if (Array.isArray(nav.languages)) {
60
+ for (i = 0; i < nav.languages.length; i++) {
61
+ language = nav.languages[i];
62
+ if (language && language.length) {
63
+ return language.slice(0, 2);
64
+ }
65
+ }
66
+ }
67
+
68
+ // support for other well known properties in browsers
69
+ for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
70
+ language = nav[browserLanguagePropertyKeys[i]];
71
+ if (language && language.length) {
72
+ return language.slice(0, 2);
73
+ }
74
+ }
75
+
76
+ return null;
77
+ },
78
+ compareLangKeys() {
79
+ const en = Object.keys(enLocale.state);
80
+ const de = Object.keys(deLocale.state);
81
+ const es = Object.keys(esLocale.state);
82
+ const kr = Object.keys(krLocale.state);
83
+ const it = Object.keys(itLocale.state);
84
+ const fr = Object.keys(frLocale.state);
85
+ const sr = Object.keys(srLocale.state);
86
+ const tr = Object.keys(trLocale.state);
87
+
88
+ // Compare en and de
89
+ console.log(
90
+ 'In en but not in de',
91
+ en.filter((x) => !de.includes(x))
92
+ );
93
+ console.log(
94
+ 'In de but not in en',
95
+ de.filter((x) => !en.includes(x))
96
+ );
97
+ console.log();
98
+
99
+ // Compare en and es
100
+ console.log(
101
+ 'In en but not in es',
102
+ en.filter((x) => !es.includes(x))
103
+ );
104
+ console.log(
105
+ 'In es but not in en',
106
+ es.filter((x) => !en.includes(x))
107
+ );
108
+ console.log();
109
+
110
+ // Compare en and kr
111
+ console.log(
112
+ 'In en but not in kr',
113
+ en.filter((x) => !kr.includes(x))
114
+ );
115
+ console.log(
116
+ 'In kr but not in en',
117
+ kr.filter((x) => !en.includes(x))
118
+ );
119
+ console.log();
120
+
121
+ // Compare en and it
122
+ console.log(
123
+ 'In en but not in it',
124
+ en.filter((x) => !it.includes(x))
125
+ );
126
+ console.log(
127
+ 'In it but not in en',
128
+ it.filter((x) => !en.includes(x))
129
+ );
130
+ console.log();
131
+
132
+ // Compare en and fr
133
+ console.log(
134
+ 'In en but not in fr',
135
+ en.filter((x) => !fr.includes(x))
136
+ );
137
+ console.log(
138
+ 'In fr but not in en',
139
+ fr.filter((x) => !en.includes(x))
140
+ );
141
+ console.log();
142
+
143
+ // Compare en and sr
144
+ console.log(
145
+ 'In en but not in sr',
146
+ en.filter((x) => !sr.includes(x))
147
+ );
148
+ console.log(
149
+ 'In sr but not in en',
150
+ sr.filter((x) => !en.includes(x))
151
+ );
152
+ console.log();
153
+
154
+ // Compare en and tr
155
+ console.log(
156
+ 'In en but not in tr',
157
+ en.filter((x) => !tr.includes(x))
158
+ );
159
+ console.log(
160
+ 'In tr but not in en',
161
+ tr.filter((x) => !en.includes(x))
162
+ );
163
+ console.log();
164
+ },
165
+ base64ImageToBlob(base64Image) {
166
+ // Split into two parts
167
+ const parts = base64Image.split(';base64,');
168
+
169
+ // Hold the content type
170
+ const imageType = parts[0].split(':')[1];
171
+
172
+ // Decode Base64 string
173
+ const decodedData = window.atob(parts[1]);
174
+
175
+ // Create UNIT8ARRAY of size same as row data length
176
+ const uInt8Array = new Uint8Array(decodedData.length);
177
+
178
+ // Insert all character code into uInt8Array
179
+ for (let i = 0; i < decodedData.length; ++i) {
180
+ uInt8Array[i] = decodedData.charCodeAt(i);
181
+ }
182
+
183
+ // Return BLOB image after conversion
184
+ return new Blob([uInt8Array], { type: imageType });
185
+ },
186
+ blobToBase64(blob) {
187
+ const reader = new FileReader();
188
+ reader.readAsDataURL(blob);
189
+ return new Promise((resolve) => {
190
+ reader.onloadend = () => {
191
+ resolve(reader.result);
192
+ };
193
+ });
194
+ },
195
+ base64toFile(base64, filename) {
196
+ var arr = base64.split(','),
197
+ mime = arr[0].match(/:(.*?);/)[1],
198
+ bstr = atob(arr[1]),
199
+ n = bstr.length,
200
+ u8arr = new Uint8Array(n);
201
+
202
+ while (n--) {
203
+ u8arr[n] = bstr.charCodeAt(n);
204
+ }
205
+
206
+ return new File([u8arr], filename, { type: mime });
207
+ },
208
+ fileToBase64(file) {
209
+ new Promise((resolve, reject) => {
210
+ const reader = new FileReader();
211
+ reader.readAsDataURL(file);
212
+ reader.onload = () => resolve(reader.result);
213
+ reader.onerror = (error) => reject(error);
214
+ });
215
+ },
216
+ getUTMParams(data) {
217
+ let utm = {};
218
+ if (data.utm_source) utm.utm_source = data.utm_source;
219
+ if (data.utm_medium) utm.utm_medium = data.utm_medium;
220
+ if (data.utm_campaign) utm.utm_campaign = data.utm_campaign;
221
+ if (data.utm_term) utm.utm_term = data.utm_term;
222
+ if (data.utm_content) utm.utm_content = data.utm_content;
223
+ return utm;
224
+ },
225
+
226
+ cropCardScan(base64PictureData, callback) {
227
+ // image will contain ORIGINAL image
228
+ const image = new window.Image();
229
+
230
+ // image will contain CROPPED image
231
+ const canvas = document.createElement('canvas');
232
+ const ctx = canvas.getContext('2d');
233
+
234
+ // Load original image into image element
235
+ image.src = 'data:image/jpeg;base64,' + base64PictureData;
236
+ image.onload = () => {
237
+ const sw = image.width;
238
+ const sh = image.width / 1.65;
239
+ const sx = 0;
240
+ const sy = image.height / 2 - sh / 2;
241
+ const dw = sw;
242
+ const dh = sh;
243
+ canvas.width = dw;
244
+ canvas.height = dh;
245
+ // https://i.stack.imgur.com/USDAX.png
246
+ ctx.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh); // Crop interpolated rectangle
247
+ const croppedBase64Image = canvas.toDataURL();
248
+
249
+ callback(croppedBase64Image);
250
+
251
+ return croppedBase64Image;
252
+ };
253
+ },
254
+ generateRandomString(length) {
255
+ let array = new Uint32Array(length);
256
+ getRandomValues(array);
257
+ return Array.from(array, (dec) => ('0' + dec.toString(16)).substr(-2)).join('');
258
+ },
259
+ async pkceChallengeFromVerifier(v) {
260
+ try {
261
+ const encoder = new TextEncoder();
262
+ const data = encoder.encode(v);
263
+ const hashed = await performDigest(data);
264
+ const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(hashed)))
265
+ .replace(/\+/g, '-')
266
+ .replace(/\//g, '_')
267
+ .replace(/=+$/, '');
268
+ return base64;
269
+ } catch (error) {
270
+ const hash = sha256(v);
271
+ const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(hash.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))))
272
+ .replace(/\+/g, '-')
273
+ .replace(/\//g, '_')
274
+ .replace(/=+$/, '');
275
+ return base64;
276
+ }
277
+ },
278
+ async encryptAES(key, iv, data) {
279
+ try {
280
+ let encoder = new TextEncoder();
281
+ let encoded = encoder.encode(data);
282
+ return await performEncrypt(
283
+ {
284
+ name: 'AES-CBC',
285
+ iv: iv
286
+ },
287
+ key,
288
+ encoded
289
+ );
290
+ } catch (error) {
291
+ throw error;
292
+ }
293
+ },
294
+ async decryptAES(key, iv, data) {
295
+ try {
296
+ const fromBase64 = (base64String) => Uint8Array.from(atob(base64String), (c) => c.charCodeAt(0));
297
+
298
+ data = data.replace(/ /g, '+');
299
+
300
+ const encoder = new TextEncoder();
301
+ const decoder = new TextDecoder();
302
+
303
+ key = encoder.encode(key);
304
+ iv = encoder.encode(iv);
305
+ data = fromBase64(data);
306
+
307
+ const secretKey = await window.crypto.subtle.importKey('raw', key, 'AES-CBC', true, ['encrypt', 'decrypt']);
308
+
309
+ let decoded = await performDecrypt({ name: 'AES-CBC', iv }, secretKey, data);
310
+
311
+ decoded = decoder.decode(decoded);
312
+ decoded = decoded.replace(/ /g, '+');
313
+ decoded = atob(decoded);
314
+
315
+ return decoded;
316
+ } catch (err) {
317
+ throw err;
318
+ }
319
+ }
320
+ };