バージョン
"dependencies": {
"bcryptjs": "^2.4.3",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.11.17",
}
秘密鍵と有効期限の設定
設定ファイルに書きます。
.env
JWT_SECRET=somesecretkey
JWT_EXPIRED=30d
User スキーマ
email
とpassword
のみのユーザーです。
const UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: [true, "Please add an Email"],
match: [
/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
"Please use a valid email address",
],
},
password: {
type: String,
required: [true, "Please add a password"],
minlength: 6,
select: false,
},
});
JWTの生成
User
モデルにJWT生成メソッドを追加します。
User
のid
を元にトークンを生成します。
import jwt from "jsonwebtoken";
UserSchema.methods.getSignedJwtToken = function () {
return jwt.sign(
{ id: this._id },
process.env.JWT_SECRET,
{ expiresIn: process.env.JWT_EXPIRED }
);
};
ユーザー登録成功時にJWTを返却
登録成功時に作成したUser
のメソッドを呼び出します。
/**
* @desc Register User
* @route POST /api/v1/auth/register
* @access Public
*/
export const register = async (req, res, next) => {
const { email, password } = req.body;
const user = await User.create({
email,
password,
});
// Token生成
const token = user.getSignedJwtToken();
res.status(200).json({ success: true, data: user, token });
};
ユーザーログイン成功時にJWTを返却
ログイン時も同様です。
/**
* @desc Login User
* @route POST /api/v1/auth/login
* @access Public
*/
export const login = (req, res, next) => {
const { email, password } = req.body;
const user = User.findOne({ email }).select("+password");
// Token生成
const token = user.getSignedJwtToken();
res.status(200).json({ success: true, token });
};
JWTを検証するミドルウェア
import jwt from "jsonwebtoken";
/**
* トークンを検証するミドルウェア
* Routesに差し込んで使用する
* 有効なトークンを持っていない場合は401エラーを返す
*/
export const protect = (req, res, next) => {
const { authorization } = req.headers;
let token: string | undefined;
// Bearer + Token を想定
if (authorization && authorization.startsWith("Bearer")) {
token = authorization.split(" ")[1];
}
if (!token) return next(new ErrorResponse("Not authorized to access this route", 401));
try {
// トークンの検証
const decoded = jwt.verify(token, process.env.JWT_SECRET!) as DecodedJwt;
req.user = await User.findById(decoded.id);
next();
} catch (err) {
return next(new ErrorResponse("Not authorized to access this route", 401));
}
});
ミドルウェアの使用
トークンが必要なルーティングに差し込んで使用します。
const router = express.Router();
router.use(protect);
router
.route("/")
.get(someProtectedRoute);