mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🔐 fix: token not using webcrypto (#4005)
* fix: token * style: auth pages updated `|` color
This commit is contained in:
parent
aea01f0bc5
commit
c3dc03b063
6 changed files with 23 additions and 14 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcryptjs');
|
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
const { getRandomValues, hashToken } = require('~/server/utils/crypto');
|
||||||
const { createToken, findToken } = require('./Token');
|
const { createToken, findToken } = require('./Token');
|
||||||
const logger = require('~/config/winston');
|
const logger = require('~/config/winston');
|
||||||
|
|
||||||
|
|
@ -18,8 +17,8 @@ const logger = require('~/config/winston');
|
||||||
*/
|
*/
|
||||||
const createInvite = async (email) => {
|
const createInvite = async (email) => {
|
||||||
try {
|
try {
|
||||||
let token = crypto.randomBytes(32).toString('hex');
|
const token = await getRandomValues(32);
|
||||||
const hash = bcrypt.hashSync(token, 10);
|
const hash = await hashToken(token);
|
||||||
const encodedToken = encodeURIComponent(token);
|
const encodedToken = encodeURIComponent(token);
|
||||||
|
|
||||||
const fakeUserId = new mongoose.Types.ObjectId();
|
const fakeUserId = new mongoose.Types.ObjectId();
|
||||||
|
|
@ -50,7 +49,7 @@ const createInvite = async (email) => {
|
||||||
const getInvite = async (encodedToken, email) => {
|
const getInvite = async (encodedToken, email) => {
|
||||||
try {
|
try {
|
||||||
const token = decodeURIComponent(encodedToken);
|
const token = decodeURIComponent(encodedToken);
|
||||||
const hash = bcrypt.hashSync(token, 10);
|
const hash = await hashToken(token);
|
||||||
const invite = await findToken({ token: hash, email });
|
const invite = await findToken({ token: hash, email });
|
||||||
|
|
||||||
if (!invite) {
|
if (!invite) {
|
||||||
|
|
@ -59,7 +58,7 @@ const getInvite = async (encodedToken, email) => {
|
||||||
|
|
||||||
return invite;
|
return invite;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[getInvite] Error getting invite', error);
|
logger.error('[getInvite] Error getting invite:', error);
|
||||||
return { error: true, message: error.message };
|
return { error: true, message: error.message };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -102,4 +102,14 @@ async function hashToken(str) {
|
||||||
return Buffer.from(hashBuffer).toString('hex');
|
return Buffer.from(hashBuffer).toString('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { encrypt, decrypt, encryptV2, decryptV2, hashToken };
|
async function getRandomValues(length) {
|
||||||
|
if (!Number.isInteger(length) || length <= 0) {
|
||||||
|
throw new Error('Length must be a positive integer');
|
||||||
|
}
|
||||||
|
|
||||||
|
const randomValues = new Uint8Array(length);
|
||||||
|
webcrypto.getRandomValues(randomValues);
|
||||||
|
return Buffer.from(randomValues).toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { encrypt, decrypt, encryptV2, decryptV2, hashToken, getRandomValues };
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error,
|
||||||
aria-invalid={!!errors.email}
|
aria-invalid={!!errors.email}
|
||||||
className="
|
className="
|
||||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||||
bg-surface-primary px-3.5 pb-2.5 pt-3 duration-200 focus:border-green-500 focus:outline-none
|
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||||
"
|
"
|
||||||
placeholder=" "
|
placeholder=" "
|
||||||
/>
|
/>
|
||||||
|
|
@ -134,7 +134,7 @@ const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error,
|
||||||
aria-invalid={!!errors.password}
|
aria-invalid={!!errors.password}
|
||||||
className="
|
className="
|
||||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||||
bg-surface-primary px-3.5 pb-2.5 pt-3 duration-200 focus:border-green-500 focus:outline-none
|
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||||
"
|
"
|
||||||
placeholder=" "
|
placeholder=" "
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ const Registration: React.FC = () => {
|
||||||
aria-invalid={!!errors[id]}
|
aria-invalid={!!errors[id]}
|
||||||
className="
|
className="
|
||||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||||
bg-surface-primary px-3.5 pb-2.5 pt-3 duration-200 focus:border-green-500 focus:outline-none
|
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||||
"
|
"
|
||||||
placeholder=" "
|
placeholder=" "
|
||||||
data-testid={id}
|
data-testid={id}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ function RequestPasswordReset() {
|
||||||
aria-invalid={!!errors.email}
|
aria-invalid={!!errors.email}
|
||||||
className="
|
className="
|
||||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||||
bg-surface-primary px-3.5 pb-2.5 pt-3 duration-200 focus:border-green-500 focus:outline-none
|
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||||
"
|
"
|
||||||
placeholder=" "
|
placeholder=" "
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ function ResetPassword() {
|
||||||
aria-invalid={!!errors.password}
|
aria-invalid={!!errors.password}
|
||||||
className="
|
className="
|
||||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||||
bg-surface-primary px-3.5 pb-2.5 pt-3 duration-200 focus:border-green-500 focus:outline-none
|
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||||
"
|
"
|
||||||
placeholder=" "
|
placeholder=" "
|
||||||
/>
|
/>
|
||||||
|
|
@ -126,7 +126,7 @@ function ResetPassword() {
|
||||||
aria-invalid={!!errors.confirm_password}
|
aria-invalid={!!errors.confirm_password}
|
||||||
className="
|
className="
|
||||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||||
bg-surface-primary px-3.5 pb-2.5 pt-3 duration-200 focus:border-green-500 focus:outline-none
|
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||||
"
|
"
|
||||||
placeholder=" "
|
placeholder=" "
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue