login-auth-services
Version:
Authentication services for Google, GitHub, Microsoft, okta and multi-factor authentication using OTP.
80 lines (68 loc) • 2.78 kB
text/typescript
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
import nodemailer from "nodemailer";
import crypto from "crypto";
import { DatabaseService } from "./databaseService";
import type { User } from "../entities/User";
const dbService = DatabaseService.getInstance();
const OTPs: Record<string, string> = {};
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASSWORD,
},
});
export const hashPassword = async (password: string, saltRounds = 10): Promise<string> => {
const salt = await bcrypt.genSalt(saltRounds);
return await bcrypt.hash(password, salt);
};
export const validatePassword = async (password: string, hashedPassword: string): Promise<boolean> => {
return await bcrypt.compare(password, hashedPassword);
};
export const generateToken = (userId: string | number, email: string): string => {
const payload = { id: userId, email };
return jwt.sign(payload, process.env.SECRET_KEY || "default_secret_key", { expiresIn: "1h" });
};
export const registerUser = async (username: string, email: string, password: string): Promise<User> => {
const existingUser = await dbService.findUserByEmail(email);
if (existingUser) {
throw new Error("User already exists");
}
const hashedPassword = await hashPassword(password);
return await dbService.createUser({ username, email, password: hashedPassword });
};
export const loginUser = async (email: string, password: string): Promise<{ user: User; token: string } | null> => {
const user = await dbService.findUserByEmail(email);
if (user && (await validatePassword(password, user.password))) {
const token = generateToken(user.id, user.email);
return { user, token };
}
return null;
};
export const initiateLoginWithEmail = async (email: string): Promise<{ message: string; success: boolean }> => {
const user = await dbService.findUserByEmail(email);
if (user) {
const otp = crypto.randomInt(100000, 999999).toString();
OTPs[email] = otp;
await transporter.sendMail({
from: process.env.EMAIL_USER,
to: email,
subject: "Your OTP for Login",
text: `Your OTP is: ${otp}`,
});
return { message: "OTP sent to your email", success: true };
}
return { message: "User not found", success: false };
};
export const validateOTP = async (email: string, otp: string): Promise<{ user: User; token: string } | null> => {
if (OTPs[email] === otp) {
delete OTPs[email];
const user = await dbService.findUserByEmail(email);
if (user) {
const token = generateToken(user.id, user.email);
return { user, token };
}
}
return null;
};