feat: enhance authentication and user management with token-based system

- Implemented robust token-based authentication with access and refresh tokens
- Added JWT token generation, verification, and rotation mechanisms
- Created services for token management, Memcached, and MinIO storage
- Enhanced user registration and login with device-specific tokens
- Added support for profile picture upload and management via MinIO
- Implemented secure password hashing with crypto
- Updated Prisma schema to support refresh tokens and profile picture storage
- Added GraphQL mutations for logout, token refresh, and profile picture handling
- Integrated environment configuration with Zod validation
- Improved error handling and authentication middleware
This commit is contained in:
Juan Sebastián Montoya 2025-03-09 22:34:57 -05:00
parent d4d99fb5e7
commit d29d116214
22 changed files with 1992 additions and 388 deletions

68
apps/api/src/config.ts Normal file
View file

@ -0,0 +1,68 @@
import { z } from 'zod';
import dotenv from 'dotenv';
import path from 'path';
const rootDir = path.resolve(process.cwd(), '../../');
dotenv.config({ path: `${rootDir}/.env.local` });
const schema = z
.object({
ALLOWED_ORIGINS: z.string(),
API_HOST: z.string(),
API_PORT: z.coerce.number(),
COOKIE_SECRET: z.string(),
MINIO_ENDPOINT: z.string(),
MINIO_PORT: z.coerce.number(),
MINIO_ACCESS_KEY: z.string(),
MINIO_SECRET_KEY: z.string(),
MINIO_BUCKET_NAME: z.string(),
MINIO_REGION: z.string().default('us-east-1'),
MINIO_USE_SSL: z.string().transform((val) => val === 'true'),
MEMC_HOST: z.string(),
MEMC_PORT: z.coerce.number(),
MEMC_TTL: z.coerce.number().default(30 * 60), // 30 minutes in seconds
MEMC_NAMESPACE: z.string().default('unreal-chat'),
NODE_ENV: z.enum(['development', 'staging', 'production']),
TOKEN_ACCESS_EXPIRES_IN: z.coerce.number().default(30 * 60), // 30 minutes in seconds
TOKEN_REFRESH_EXPIRES_IN: z.coerce.number().default(7 * 24 * 60 * 60), // 7 days in seconds
TOKEN_SECRET: z.string(),
})
.transform((env) => {
return {
isProduction: env.NODE_ENV === 'production',
server: {
allowedOrigins: env.ALLOWED_ORIGINS.split(','),
port: env.API_PORT,
host: env.API_HOST,
},
minio: {
endPoint: env.MINIO_ENDPOINT,
port: env.MINIO_PORT,
useSSL: env.MINIO_USE_SSL,
accessKey: env.MINIO_ACCESS_KEY,
secretKey: env.MINIO_SECRET_KEY,
bucketName: env.MINIO_BUCKET_NAME,
region: env.MINIO_REGION,
},
token: {
accessTokenExpiresIn: env.TOKEN_ACCESS_EXPIRES_IN,
refreshTokenExpiresIn: env.TOKEN_REFRESH_EXPIRES_IN,
secret: env.TOKEN_SECRET,
},
memc: {
host: env.MEMC_HOST,
port: env.MEMC_PORT,
ttl: env.MEMC_TTL,
namespace: env.MEMC_NAMESPACE,
},
cookie: {
secret: env.COOKIE_SECRET,
},
};
});
export type Config = z.infer<typeof schema>;
export type MinioConfig = Config['minio'];
export type TokenConfig = Config['token'];
export type MemcConfig = Config['memc'];
export default schema.parse(process.env);