Bảo mật
Xác thực
RivaLMS dùng Auth.js (NextAuth v5) với phiên JWT. Tài khoản do nhà trường cấp: người dùng đăng nhập bằng email và mật khẩu do Quản lý đào tạo hoặc Quản trị hệ thống tạo.
Cấu hình NextAuth
Cấu hình nằm trong src/lib/auth.ts.
Cấu hình chính
// src/lib/auth.ts
import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
session: { strategy: "jwt" },
pages: {
signIn: "/login",
error: "/login",
},
providers: [
Google({ ... }),
GitHub({ ... }),
Credentials({ ... }),
],
callbacks: {
async signIn({ user, account }) { ... },
async jwt({ token, user, trigger, session }) { ... },
async session({ session, token }) { ... },
},
});- Vai trò và cờ bắt buộc đổi mật khẩu được lưu trong JWT và đọc ra ở
session.user. - Cứ 5 phút, phiên đọc lại trạng thái tài khoản từ cơ sở dữ liệu, nên tài khoản bị khóa mất phiên trong tối đa 5 phút.
src/middleware.tsđọc JWT để chặn các trang theo vai trò (xem trang Vai trò & phân quyền).
Đăng nhập bằng mật khẩu
Người dùng đăng nhập bằng email và mật khẩu; mật khẩu được băm bằng bcrypt (cost 12).
Kiểm tra đăng nhập
async authorize(credentials) {
const user = await prisma.user.findUnique({
where: { email: credentials.email },
include: { role: true },
});
// Tài khoản bị khóa nhận cùng lỗi như sai mật khẩu
if (!user || !user.password || !user.isActive) return null;
const isValid = await bcrypt.compare(credentials.password, user.password);
if (!isValid) return null;
return {
id: user.id,
email: user.email,
name: user.name,
role: user.role.name,
mustChangePassword: user.mustChangePassword,
};
}Cấp tài khoản và mật khẩu
- Quản lý đào tạo tạo tài khoản Học viên và Giảng viên; Quản trị hệ thống tạo được tài khoản mọi vai trò.
- Tài khoản mới nhận một mật khẩu tạm, chỉ hiển thị một lần. Ở lần đăng nhập đầu, người dùng phải đổi mật khẩu tại
/change-passwordrồi mới vào được hệ thống. - Khi đặt lại mật khẩu, người quản lý nhận một mật khẩu tạm mới và người dùng lại phải đổi mật khẩu ở lần đăng nhập sau.
- Mật khẩu mới có ít nhất 10 ký tự.
- Tự đăng ký tắt mặc định (
ALLOW_SELF_REGISTER=false):/registervàPOST /api/auth/registertrả 404.
Nhà cung cấp OAuth
Nút Google và GitHub trên trang đăng nhập chỉ hoạt động khi bạn đặt AUTH_GOOGLE_ID/AUTH_GOOGLE_SECRET hoặc AUTH_GITHUB_ID/AUTH_GITHUB_SECRET. Khai báo URL callback sau với nhà cung cấp:
${AUTH_URL}/api/auth/callback/google
${AUTH_URL}/api/auth/callback/githubCân nhắc trước khi bật
Người đăng nhập bằng OAuth lần đầu được tự tạo tài khoản Học viên, bỏ qua quy trình cấp tài khoản của nhà trường. Đăng nhập SSO bằng tài khoản Microsoft 365 hoặc Google Workspace của trường đang được lên kế hoạch (FR-AUTH-03).