Hướng Dẫn Cài Đặt Passport.js với Chiến Lược Google OAuth
Giới thiệu
Trong bài viết này, chúng ta sẽ tìm hiểu cách cài đặt và cấu hình Passport.js với chiến lược OAuth 2.0 của Google để cho phép người dùng đăng nhập bằng tài khoản Google của họ. Việc sử dụng Passport.js giúp đơn giản hóa quá trình xác thực và quản lý phiên làm việc cho người dùng trong ứng dụng Node.js của chúng ta.
Mục tiêu của chúng ta
- Thiết lập xác thực người dùng bằng tài khoản Google.
- Tạo và quản lý token JWT cho người dùng đã xác thực.
- Cấu hình các route cho quá trình đăng nhập và callback.
Cài đặt Passport.js
Đầu tiên, bạn cần cài đặt các gói cần thiết:
bash
npm install passport passport-google-oauth20 express-session
Cấu hình Passport.js
Trong tệp cấu hình chính của Passport.js, chúng ta sẽ thiết lập chiến lược với client ID, client secret và callback URL được cung cấp bởi Google. Dưới đây là đoạn mã mẫu cho việc cấu hình:
typescript
import { Request } from "express";
import passport from "passport";
import { Strategy, Profile, VerifyCallback } from "passport-google-oauth20";
import { User } from "../models/userModel";
passport.use(
new Strategy(
{
clientID: process.env.CLIENT_ID || "",
clientSecret: process.env.CLIENT_SECRET || "",
callbackURL: process.env.CALLBACK_URL_PASSPORT,
passReqToCallback: true,
},
async (
req: Request,
accessToken: string,
refreshToken: string,
profile: Profile,
done: VerifyCallback
) => {
try {
let user = await User.findOne({
googleId: profile.id,
});
if (!user) {
user = await User.create({
googleId: profile.id,
fullName: profile.displayName,
email: profile.emails?.[0]?.value,
profilePicture: profile.photos?.[0]?.value,
});
}
return done(null, user);
} catch (error) {
return done(error);
}
}
)
);
Tạo JWT cho người dùng đã xác thực
Sau khi Passport xác thực thành công người dùng, chúng ta cần tạo hệ thống xác thực riêng cho ứng dụng. Chúng ta sẽ tạo hai token JWT: một access token (ngắn hạn, dành cho các yêu cầu API) và một refresh token (dài hạn, dùng để lấy token mới). Các token này sẽ được tạo trong phương thức googleCallback
của AuthController
.
Dưới đây là đoạn mã mẫu cho việc tạo và lưu trữ token:
typescript
export class AuthController {
public googleCallback = asyncHandler(
async (req: Request, res: Response): Promise<void> => {
const user = req.user as IUser;
if (!user) {
throw new ApiError(403, "Permission Denied");
}
const refreshToken = user.generateRefreshToken();
const accessToken = user.generateAccessToken();
res.cookie("accessToken", accessToken, {
httpOnly: true,
secure: true,
path: "/",
sameSite: "none"
});
res.cookie("refreshToken", refreshToken, {
httpOnly: true,
secure: true,
sameSite: "none",
path: "/"
});
res.redirect(
`http://localhost:5173/oauth-success?accessToken=${accessToken}&refreshToken=${refreshToken}`
);
}
);
}
Cấu hình và sử dụng route
Để hoàn tất quá trình xác thực, chúng ta cần định nghĩa hai route trong googleRoutes.ts
. Route đầu tiên, GET /google
, khởi động quy trình đăng nhập Google bằng cách gọi passport.authenticate("google", { scope: ["profile", "email"] })
, điều này sẽ chuyển hướng người dùng đến trang đăng nhập của Google.
Route thứ hai, GET /google/callback
, là endpoint mà Google sẽ gọi lại sau khi người dùng đăng nhập thành công. Tại đây, Passport sẽ chạy lại chiến lược, gắn người dùng vào req.user
, và sau đó chuyển điều khiển đến phương thức googleCallback
trong controller của chúng ta.
Dưới đây là mã mẫu cho việc cấu hình route:
typescript
router.get(
"/google",
passport.authenticate("google", {
scope: ["profile", "email"],
})
);
router.get(
"/google/callback",
passport.authenticate("google", {
session: false,
failureRedirect: "/login",
}),
googleCallback
);
Các thực hành tốt nhất
- Bảo mật thông tin người dùng: Luôn lưu trữ client secret và token trong biến môi trường và không để lộ ra mã nguồn.
- Kiểm tra lỗi: Thêm các cơ chế kiểm tra lỗi cho các trường hợp không thành công trong quá trình xác thực.
Những cạm bẫy thường gặp
- Không xử lý được lỗi: Đảm bảo rằng bạn xử lý tất cả các lỗi có thể xảy ra trong quá trình xác thực, chẳng hạn như khi người dùng không cho phép quyền truy cập.
- Không sử dụng HTTPS: Khi triển khai, luôn sử dụng HTTPS để bảo mật dữ liệu nhạy cảm.
Mẹo hiệu suất
- Giảm thiểu số lần truy vấn cơ sở dữ liệu: Sử dụng caching để lưu trữ thông tin người dùng đã xác thực.
- Tối ưu hóa việc sử dụng token: Giảm thời gian sống của access token để giảm nguy cơ lạm dụng.
Giải quyết vấn đề
- Người dùng không thể đăng nhập: Kiểm tra client ID và client secret trong biến môi trường.
- Lỗi khi gọi lại từ Google: Đảm bảo rằng callback URL được cấu hình chính xác trong thiết lập Google API.
Kết luận
Việc cài đặt Passport.js với chiến lược Google OAuth không chỉ giúp đơn giản hóa quá trình xác thực mà còn nâng cao bảo mật cho ứng dụng của bạn. Hãy chắc chắn rằng bạn đã kiểm tra kỹ lưỡng mọi phần của quy trình để đảm bảo tính toàn vẹn và an toàn cho dữ liệu người dùng. Bạn có thể tham khảo thêm tài liệu trên trang chính thức của Passport.js để nâng cao kiến thức và kỹ năng của mình.
Câu hỏi thường gặp
1. Passport.js là gì?
Passport.js là một middleware cho Node.js giúp quản lý xác thực người dùng dễ dàng hơn.
2. Tại sao nên sử dụng OAuth 2.0?
OAuth 2.0 cho phép người dùng đăng nhập bằng tài khoản của họ mà không cần phải tạo tài khoản mới, tăng tính tiện lợi và bảo mật.
3. Có những chiến lược nào khác ngoài Google?
Có nhiều chiến lược khác như Facebook, Twitter, GitHub, v.v.
4. Tôi có thể sử dụng Passport.js với framework nào?
Passport.js có thể được sử dụng với bất kỳ framework nào hỗ trợ middleware như Express.js.