LoginSignup
6

More than 5 years have passed since last update.

Node.js + Express + TypeScriptでWebAPIを作る(4/4)

Posted at

概要

  • ログインと手探りでJWT認証を実装する

JWT認証は手探りなのであってるか不安:thinking:

ログイン処理実装

通常ログイン+JWT認証を利用しようと思います。今回はパスワードのハッシュ化は省略しますが、パスワードを生で持つことは止めましょう。具体的に言うとオランウータンに核爆弾のスイッチを掃除させるぐらいに危険です。
ってことでまずはuidとpasswordをPostしてPostされたPasswordとDBにあるパスワードが一致しているか見て、一致していたらTokenを返すところまで実装します。要するに通常のログインです。

// ./src/rotes/auth/index.ts
import Express from "express";
import jwt from "jsonwebtoken";
import mongodbClient from "../../dbClient";
import IDocumentUser from "../../documents/IdocumentUser";
import noImpl from "../../noImpl";

const router = Express.Router();

router.delete("/signout", noImpl);

router.post("/signin", (req, res, next) => {
    const uid: string = req.body.uid;
    console.log(req.body);
    mongodbClient((ce, client, db) => {
        if (ce) {
            client.close();
            res.status(500);
            res.json({
                message: ce.message,
                requestPath: req.path,
            });
            return next(ce);
        }

        const collection = db.collection<IDocumentUser>("users");
        collection.findOne({ uid }, (e, result) => {
            if (e) {
                client.close();
                res.status(500);
                res.json({
                    message: e.message,
                    requestPath: req.path,
                });
                return next(e);
            }

            client.close();

            if (result === null || result.password !== req.body.password) {
                res.json({ signin: false, message: "nothing uid or missing password" });
                return;
            } else {
                const payload = {
                    name: result.uid,
                };
                const token: string = jwt.sign(payload, "secretKey");
                res.json({
                    success: true,
                    token,
                });
            }
        });
    });
});

export default router;
> curl -X POST -H "Content-Type: application/json" -d '{"uid":"1", "password":"piyo"}' localhost:3000/auth/signin
{"success":true,"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMSIsImlhdCI6MTU0NTcwNDQxM30.IS-4u24T1KZrZTXFynWRsMwDxs9WiH7GAan0CEakhHo"}

こんな感じでしょうか。

JWT認証実装

続いてJWT認証を実装していきます。と、その前にdbClient.ts, noImpl.ts, log.tsもcommonディレクトリに移動しておきましょう。とりあえずぶっ込んでおきます。IDocumentUser.tsは名前が長いのでIUser.tsに直していきましょう。手直ししたくなる病にかかった感あります。

// ./src/common/verifyToken.ts
import { NextFunction, Request, Response } from "express";
import jwt, { VerifyOptions } from "jsonwebtoken";

export default (req: Request, res: Response, next: NextFunction) => {
    const token = req.body.token || req.query.token || req.headers["x-access-token"];

    if (token) {
        jwt.verify(token, "secretKey", (error: any, decoded: any) => {
            if (error) {
                res.status(403);
                return res.json({ success: false, message: "Authentication of token failed." });
            } else {
                console.log(decoded);
                next();
            }
        });
    } else {
        res.status(403);
        res.json({
            message: "Token nothing.",
            success: false,
        });
    }
};

とりあえずこんな感じで実装。簡単に書いてるけど結構時間使った(´・ω・`)と言うかdecodedの受け渡しが上手くいかない...Requestを拡張したInterface作れば解決しそう。

server.tsのルーティングにVerifyTokenをかませる。

// ./src/server.ts
import verifyToken from "./common/verifyToken";

app.use("/users", verifyToken, users);
app.use("/test", verifyToken, test);

authには通さないでOK。authって名前も何か違う感半端ねぇ。
さすがにcurlでx-access-token付けて投げるの面倒なのでPostmanから投げる。まずは/auth/signin{"uid":"1", "password":"piyo"}をPostしてTokenを取得。/test/dbConnectにPostする時にheaderにx-access-tokenを含める。値は/auth/signinで返ってきたtokenを設定。{ "msg": ":-)" }が返ってくればJWT認証成功。tokenをてきとーに改変してPostすると以下のようなjsonが返却される。

{
    "success": false,
    "message": "Authentication of token failed."
}

環境作って簡単にルーティング設定して、DB接続して、DB読み(書きもできたようなもん)、JWT認証までざーっと通しました。おそらくこの内容+αでJavascript(Node.js + Express + TypeScript)を使って「動くWeb API」は実装できるかと思います。

出来上がったやつ

必要無いかもしれませんが、置いときます。
yoshida-san/js-web-api: Node.js + Express + TypescriptでWeb APIを作る(プロトタイプ)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6