@arex95/vue-core 1.1.11 → 1.1.12
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.
|
@@ -16,8 +16,8 @@ export declare function configureAuth(options: AuthConfig): void;
|
|
|
16
16
|
*/
|
|
17
17
|
export declare function useAuth(secretKey?: string): {
|
|
18
18
|
isAuthenticated: import("vue").ComputedRef<boolean>;
|
|
19
|
-
jwt: import("vue").
|
|
20
|
-
refresh_token: import("vue").
|
|
19
|
+
jwt: import("vue").Ref<string | null, string | null>;
|
|
20
|
+
refresh_token: import("vue").Ref<string | null, string | null>;
|
|
21
21
|
tokenExpiry: import("vue").ComputedRef<number | null>;
|
|
22
22
|
login: (params: {} | undefined, isRememberMe: boolean) => Promise<import("axios").AxiosResponse<any, any>>;
|
|
23
23
|
refresh: () => Promise<import("axios").AxiosResponse<any, any> | undefined>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare function useApiActivity(sessionTimeoutMin: number, checkIntervalSec: number): {
|
|
2
|
-
pause: import("@vueuse/
|
|
3
|
-
resume: import("@vueuse/
|
|
2
|
+
pause: import("@vueuse/core").Fn;
|
|
3
|
+
resume: import("@vueuse/core").Fn;
|
|
4
4
|
updateTimestamp: () => void;
|
|
5
5
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { useTimeoutFn, useBreakpoints, breakpointsTailwind, useWindowSize } from '@vueuse/core';
|
|
1
|
+
import { useTimeoutFn, useBreakpoints, breakpointsTailwind, useWindowSize, computedAsync } from '@vueuse/core';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { useRouter } from 'vue-router';
|
|
4
4
|
import { useQuery } from '@tanstack/vue-query';
|
|
5
5
|
import { ref, watch, onServerPrefetch, onMounted, computed } from 'vue';
|
|
6
|
-
import * as CryptoJS from 'crypto-js';
|
|
7
6
|
import { jwtDecode } from 'jwt-decode';
|
|
8
7
|
import { v4 } from 'uuid';
|
|
9
8
|
|
|
@@ -3013,42 +3012,67 @@ function configureAuth(options) {
|
|
|
3013
3012
|
config.storageKeys = { ...config.storageKeys, ...options.storageKeys };
|
|
3014
3013
|
}
|
|
3015
3014
|
}
|
|
3015
|
+
function ab2hex(buffer) {
|
|
3016
|
+
return Array.from(buffer)
|
|
3017
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
3018
|
+
.join("");
|
|
3019
|
+
}
|
|
3020
|
+
function hex2ab(hex) {
|
|
3021
|
+
return new Uint8Array(hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
|
3022
|
+
}
|
|
3023
|
+
async function importKey(secretKey) {
|
|
3024
|
+
const encoder = new TextEncoder();
|
|
3025
|
+
const keyMaterial = await crypto.subtle.digest("SHA-256", encoder.encode(secretKey));
|
|
3026
|
+
return await crypto.subtle.importKey("raw", keyMaterial, { name: "AES-CBC", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
3027
|
+
}
|
|
3016
3028
|
/**
|
|
3017
|
-
* Encrypts a value using AES encryption.
|
|
3029
|
+
* Encrypts a value using AES-256 CBC encryption with Web Cryptography API.
|
|
3030
|
+
* The IV is generated randomly for each encryption and prepended to the ciphertext.
|
|
3018
3031
|
*
|
|
3019
3032
|
* @param {string} value - The value to encrypt.
|
|
3020
|
-
* @param {string}
|
|
3021
|
-
* @returns {string}
|
|
3022
|
-
*/
|
|
3023
|
-
const encrypt = (value,
|
|
3024
|
-
|
|
3033
|
+
* @param {string} secretKey - The encryption key string.
|
|
3034
|
+
* @returns {Promise<string>} A promise that resolves to the encrypted string (hex IV + hex ciphertext).
|
|
3035
|
+
*/
|
|
3036
|
+
const encrypt = async (value, secretKey) => {
|
|
3037
|
+
const key = await importKey(secretKey);
|
|
3038
|
+
const textEncoder = new TextEncoder();
|
|
3039
|
+
const data = textEncoder.encode(value);
|
|
3040
|
+
const iv = crypto.getRandomValues(new Uint8Array(16));
|
|
3041
|
+
const encryptedContentBuffer = await crypto.subtle.encrypt({ name: "AES-CBC", iv: iv }, key, data);
|
|
3042
|
+
const encryptedContentUint8 = new Uint8Array(encryptedContentBuffer);
|
|
3043
|
+
return ab2hex(iv) + ab2hex(encryptedContentUint8);
|
|
3025
3044
|
};
|
|
3026
3045
|
/**
|
|
3027
|
-
* Decrypts an AES encrypted value.
|
|
3046
|
+
* Decrypts an AES-256 CBC encrypted value using Web Cryptography API.
|
|
3047
|
+
* The IV is extracted from the beginning of the encrypted string.
|
|
3028
3048
|
*
|
|
3029
|
-
* @param {string} value - The encrypted
|
|
3030
|
-
* @param {string}
|
|
3031
|
-
* @returns {string}
|
|
3032
|
-
*/
|
|
3033
|
-
const decrypt = (value,
|
|
3034
|
-
const
|
|
3035
|
-
|
|
3049
|
+
* @param {string} value - The encrypted string (hex IV + hex ciphertext).
|
|
3050
|
+
* @param {string} secretKey - The decryption key string.
|
|
3051
|
+
* @returns {Promise<string>} A promise that resolves to the decrypted string.
|
|
3052
|
+
*/
|
|
3053
|
+
const decrypt = async (value, secretKey) => {
|
|
3054
|
+
const key = await importKey(secretKey);
|
|
3055
|
+
const iv = hex2ab(value.substring(0, 32));
|
|
3056
|
+
const encryptedData = hex2ab(value.substring(32));
|
|
3057
|
+
const decryptedContent = await crypto.subtle.decrypt({ name: "AES-CBC", iv: iv }, key, encryptedData);
|
|
3058
|
+
return new TextDecoder().decode(decryptedContent);
|
|
3036
3059
|
};
|
|
3037
3060
|
/**
|
|
3038
3061
|
* Stores an encrypted value in sessionStorage or localStorage.
|
|
3039
3062
|
*
|
|
3040
3063
|
* @param {string} key - Storage key.
|
|
3041
|
-
* @param {
|
|
3064
|
+
* @param {string} value - Value to store.
|
|
3042
3065
|
* @param {string} secretKey - Encryption key.
|
|
3043
3066
|
* @param {boolean} isRememberMe - Whether to store in localStorage.
|
|
3044
3067
|
* @param {number} [attempt=0] - Retry attempt count.
|
|
3045
3068
|
* @returns {Promise<void>}
|
|
3046
3069
|
*/
|
|
3047
|
-
const storeEncryptedItem = async (
|
|
3070
|
+
const storeEncryptedItem = async (key, value, secretKey, isRememberMe, attempt = 0) => {
|
|
3048
3071
|
const storage = isRememberMe ? localStorage : sessionStorage;
|
|
3049
3072
|
if (typeof window !== "undefined" && storage) {
|
|
3050
3073
|
try {
|
|
3051
|
-
|
|
3074
|
+
const encryptedValue = await encrypt(value, secretKey);
|
|
3075
|
+
storage.setItem(key, encryptedValue);
|
|
3052
3076
|
return;
|
|
3053
3077
|
}
|
|
3054
3078
|
catch (error) {
|
|
@@ -3074,13 +3098,15 @@ const storeEncryptedItem = async (value, key, secretKey, isRememberMe, attempt =
|
|
|
3074
3098
|
* @param {string} key - Storage key.
|
|
3075
3099
|
* @param {string} secretKey - Decryption key.
|
|
3076
3100
|
* @param {boolean} isRememberMe - Whether to retrieve from localStorage.
|
|
3077
|
-
* @returns {string|null} The decrypted value or null.
|
|
3101
|
+
* @returns {Promise<string|null>} The decrypted value or null.
|
|
3078
3102
|
*/
|
|
3079
|
-
function getDecryptedValue(key, secretKey, isRememberMe) {
|
|
3103
|
+
async function getDecryptedValue(key, secretKey, isRememberMe) {
|
|
3080
3104
|
const storage = sessionStorage;
|
|
3081
3105
|
try {
|
|
3082
3106
|
const value = storage.getItem(key);
|
|
3083
|
-
|
|
3107
|
+
if (!value)
|
|
3108
|
+
return null;
|
|
3109
|
+
return await decrypt(value, secretKey);
|
|
3084
3110
|
}
|
|
3085
3111
|
catch (error) {
|
|
3086
3112
|
handleError(error, false);
|
|
@@ -3094,8 +3120,8 @@ function getDecryptedValue(key, secretKey, isRememberMe) {
|
|
|
3094
3120
|
* @returns {Object} Auth composable methods and properties.
|
|
3095
3121
|
*/
|
|
3096
3122
|
function useAuth(secretKey = getSecretKey()) {
|
|
3097
|
-
const jwt =
|
|
3098
|
-
const refresh_token =
|
|
3123
|
+
const jwt = computedAsync(async () => await getDecryptedValue(config.storageKeys.ACCESS_TOKEN, secretKey), null);
|
|
3124
|
+
const refresh_token = computedAsync(async () => await getDecryptedValue(config.storageKeys.REFRESH_TOKEN, secretKey), null);
|
|
3099
3125
|
/**
|
|
3100
3126
|
* Computes token expiration timestamp.
|
|
3101
3127
|
*/
|
|
@@ -3172,7 +3198,7 @@ function useAuth(secretKey = getSecretKey()) {
|
|
|
3172
3198
|
* Clears stored authentication data.
|
|
3173
3199
|
*/
|
|
3174
3200
|
const cleanStorage = async () => {
|
|
3175
|
-
Object.keys(config.storageKeys).forEach(key => {
|
|
3201
|
+
Object.keys(config.storageKeys).forEach((key) => {
|
|
3176
3202
|
sessionStorage.removeItem(config.storageKeys[key]);
|
|
3177
3203
|
localStorage.removeItem(config.storageKeys[key]);
|
|
3178
3204
|
});
|
|
@@ -3182,9 +3208,9 @@ function useAuth(secretKey = getSecretKey()) {
|
|
|
3182
3208
|
*/
|
|
3183
3209
|
const verifyToken = async () => {
|
|
3184
3210
|
if (!jwt.value) {
|
|
3185
|
-
handleError(
|
|
3211
|
+
handleError("TOKEN_MISSING: No valid token found", true, "/auth-error", "query");
|
|
3186
3212
|
await cleanStorage();
|
|
3187
|
-
throw new Error(
|
|
3213
|
+
throw new Error("TOKEN_MISSING: No valid token found");
|
|
3188
3214
|
}
|
|
3189
3215
|
try {
|
|
3190
3216
|
const decoded = jwtDecode(jwt.value);
|
|
@@ -3212,7 +3238,7 @@ function useAuth(secretKey = getSecretKey()) {
|
|
|
3212
3238
|
refresh,
|
|
3213
3239
|
logout,
|
|
3214
3240
|
cleanStorage,
|
|
3215
|
-
verifyToken
|
|
3241
|
+
verifyToken,
|
|
3216
3242
|
};
|
|
3217
3243
|
}
|
|
3218
3244
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arex95/vue-core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.12",
|
|
4
4
|
"description": "Opinionated Vue Core",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
"axios": ">=1.6.0",
|
|
36
36
|
"uuid": ">=11.1.0",
|
|
37
37
|
"vue": ">=3.0.0",
|
|
38
|
-
"vue-router": ">=4.5.0"
|
|
38
|
+
"vue-router": ">=4.5.0",
|
|
39
|
+
"crypto-js": "^4.2.0",
|
|
40
|
+
"jwt-decode": "^4.0.0"
|
|
39
41
|
},
|
|
40
42
|
"devDependencies": {
|
|
41
43
|
"@eslint/js": "^9.23.0",
|