1. ホーム
  2. jwt

[解決済み] JWT認証のための秘密鍵とは何ですか?

2022-10-05 09:44:32

質問

最近、JWTベースの認証に取り組み始めました。ユーザーがログインした後、次のようなユーザートークンが生成されます。

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ".

これはドット(.)で区切られた3つの部分から成っています。最初の部分はBase64でエンコードされたヘッダです。デコードすると、次のようなものが得られます。

{
  "alg": "HS256", //Algorithm used
  "typ": "JWT"
}

2番目の部分はクレームで、Base64エンコードされています。デコードすると、次のようになります。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

3番目の部分は署名で、これは

HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    *secret base64 encoded*
  )  

さて、この秘密鍵とは何でしょうか、そしてこの秘密鍵をどのように生成するのでしょうか。

私はいくつかのオンラインジェネレータを試してみました "のような。 http://kjur.github.io/jsjws/tool_jwt.html のようなオンライン ジェネレータを試してみました。 のようなオンラインジェネレータを試しましたが、あまり役に立ちませんでした。

どのように解決するのですか?

Json Web Tokenは3つの部分から構成されています。ヘッダー、ペイロード、署名です。ヘッダーはトークン自体に関する単なるメタデータで、ペイロードはトークンにエンコードできるデータ、つまり本当に必要なあらゆるデータです。つまり、ここでエンコードしたいデータが多ければ多いほど、JWTは大きくなります。とにかく、この2つの部分は単なるプレーンテキストで、エンコードされますが、暗号化されることはありません。

だから誰でもそれらをデコードして読むことができます。 というわけで、ここに機密データを保存することはできません。しかし、それは全く問題ではありません。なぜなら、3番目の部分、つまり署名において、物事が本当に面白くなる場所だからです。署名はヘッダー、ペイロード、そしてサーバーに保存されている秘密を使って作成されます。

そしてこのプロセス全体は Json ウェブ トークンに署名する . 署名アルゴリズムは、ヘッダ、ペイロード、およびシークレットを使用して、一意の署名を作成します。つまり、このデータとシークレットだけが、この署名を作成することができるのです。 そして、ヘッダーとペイロードと一緒に、これらの署名がJWTを形成します。 を形成し、クライアントに送信されます。

保護されたルートへのアクセスを許可する JWT を受け取ると、サーバーはそれを検証して、ユーザーが本当に本人であるかどうかを判断する必要があります。言い換えれば、トークンのヘッダーとペイロードデータが誰にも変更されていないかどうかを検証します。つまり、この検証ステップでは、第三者が実際に Json Web Token のヘッダーとペイロードのいずれかを変更していないかどうかを確認することになります。

では、この検証は実際にどのように行われるのでしょうか。まあ、実際には非常に簡単です。JWTを受信すると、検証はそのヘッダーとペイロードを取得し、サーバーに保存されている秘密と共に、基本的にテスト署名を作成します。

しかし、JWTが最初に作成されたときに生成されたオリジナルの署名は、まだトークンの中にありますよね?これが今回の検証のキーポイントです。なぜなら、あとはテスト署名とオリジナル署名を比較するだけだからです。 そして、もしテスト署名がオリジナル署名と同じであれば、ペイロードとヘッダーが変更されていないことを意味するのです。

なぜなら、もしデータが変更されていれば、テストの署名は異なるものにならざるを得ないからです。したがって、データが変更されていないこのケースでは、ユーザーを認証することができます。もちろん、2つの署名が実際に異なる場合 が異なる場合は、誰かがデータを改ざんしたことになります。 通常、ペイロードを変更しようとすることによって。しかし、ペイロードを操作する第三者は、もちろん秘密にアクセスできないので、JWTに署名することはできません。 つまり、オリジナルの署名は、操作されたデータには決して対応しないのです。 したがって、この場合、検証は必ず失敗します。そしてこれが、このシステム全体を機能させる鍵なのです。JWTをとてもシンプルにしている魔法です。 しかし、非常に強力でもあります。

では、nodejsを使っていくつか練習してみましょう。

設定ファイルは、JWT SECRETデータを保存するのに最適なものです。署名に標準的なHSA 256暗号を使用し、秘密は少なくとも32文字であるべきですが、長ければ長いほどよいです。

config.env:

JWT_SECRET = my-32-character-ultra-secure-and-ultra-long-secret
//after 90days JWT will no longer be valid, even the signuter is correct and everything is matched.
JWT_EXPIRES_IN=90

コマンドでJWTをインストールします。

npm i jsonwebtoken


ユーザーがサインアップした後、JWTトークンを渡してログイン状態を維持し、リソースにアクセスできるようにする例です。

exports.signup = catchAsync(async (req, res, next) => {
  const newUser = await User.create({
    name: req.body.name,
    email: req.body.email,
    password: req.body.password,
    passwordConfirm: req.body.passwordConfirm,
  });
  const token = jwt.sign({ id: newUser._id }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXPIRES_IN,
  });

  res.status(201).json({
    status: 'success',
    token,
    data: {
      newUser,
    },
  });
});

を出力します。

私の意見では、超秘密のキーを生成するためにサードパーティの助けを借りてはいけません。キーボードを使用するだけです。