😀

【TypeScript × Node.js(express) × ChatGPT】JWTトークンを発行する方法

2023/02/18に公開

はじめに

本記事は、自己学習用に作成中のアプリの機能としてタイトルにある内容を実装したものです。
一部コードは話題のChatGPTが生成したものになるので、おまけとしてChatGPTとのやりとりも掲載いたします。

実装内容

※最初にコードを記載して、その後、解説となります

index.ts
import express from "express";
import mongoose from "mongoose";
import "dotenv/config";
import userApis from "./src/v1/api/userApi";

// Express FWによるローカルサーバーの立ち上げ
const app: express.Express = express();
const PORT = 4000;
const url = process.env.MONGODB_URL ? process.env.MONGODB_URL : "";

// jsonオブジェクトを扱うため
app.use(express.json());

// DB接続
try {
	mongoose.set("strictQuery", true);
	mongoose.connect(url);
	console.log("DB接続");
} catch (e) {
	console.log(e);
}

// ユーザーのAPI呼び出し
userApis(app);

app.listen(PORT, () => {
	console.log("ローカルサーバー起動中");
});

ここは、サーバーの立ち上げとDB接続して、APIを呼び出すだけの処理を書いています。

user.ts
import mongoose from "mongoose";

// userModel作成
const userSchema = new mongoose.Schema({
	username: {
		type: String,
		required: true,
		unique: true,
	},
	password: {
		type: String,
		required: true,
	},
});

module.exports = mongoose.model("User", userSchema);

これはModelで、MongoDBusernamepasswordを格納するようなスキーマにしています。

userApi.ts
import { register } from "../service/userService";
import express from "express";

const userApis = (app: express.Express) => {
	// ユーザー新規登録API
	app.post("/register", (req: express.Request, res: express.Response) => {
		register(req, res);
	});
};

export default userApis;

ここで、ユーザーに関するAPIを記述しています。
実際のビジネスロジックはregister()に記述しています。
以下、その内容です。

userService.ts
import express from "express";
import CryptoJS from "crypto-js";
import jwt from "jsonwebtoken";
import "dotenv/config";

const User = require("../models/user");

const register = async (req: express.Request, res: express.Response) => {
	// パスワードの受け取り
	const password = req.body.password;
	try {
		// パスワードの暗号化
		const key = process.env.SECRET_KEY ? process.env.SECRET_KEY : "";
		req.body.password = CryptoJS.AES.encrypt(password, key);

		// ユーザー新規作成
		const user = await User.create(req.body);

		// JWTの発行
		const secret = process.env.TOKEN_SECRET_KEY
			? process.env.TOKEN_SECRET_KEY
			: "";
		const token = jwt.sign({ id: user._id }, secret, {
			expiresIn: "24h",
		});

		return res.status(200).json({ user, token });
	} catch (e) {
		return res.status(500).json(e);
	}
};

export { register };

ポイントは、パスワードを一度、変数化し、その後に暗号化するところです。
三項演算子にしているのは、CryptoJSencrypt()に渡す際にstring型のみ許可されているためです。
dotenvprocessを介するとundefinedの可能性があるため、暗号化したパスワードをencrypt()に渡すことができません。
そのため、上記のように三項演算子としています。

ユーザーの登録に関しては、mongoosemodelにあるcreate()で行います。
その際に、引数にリクエストのbodyを渡すことでMongoDBに登録されます。

最後に、JWTの発行ですが、こちらもパスワードと同様、string型のみ引数として許可されいるため、三項演算子を用いて変数にしています。
実際にトークンを発行する処理は、jwtsign()で行い、第一引数に、一意の値としてidを渡し、第二引数にsecret_keyを、第三引数にいつまで有効かという情報を渡します。

これにより、JWTの発行によるユーザー登録が行えます。

おまけ

JWTによるトークン発行に関する簡易的な記事が見つけられなかったので、話題のchatGPTに質問してみました。

使った感想としては、個人的には、ググる能力より質問力であったり、課題を見つけ、言語化する能力がこれからのエンジニアにとっては重要なのかなと思いました。

chatGPTによるコードの生成

スクリーンショット 2023-02-18 21.22.00.png
スクリーンショット 2023-02-18 21.22.16.png

スクリーンショット 2023-02-18 21.22.27.png

Discussion