Open6
認証のコンセプト
はじめに
Udemyの「Web Developer Bootcamp2023」のセクション50「ゼロから認証」の箇所が気になったので備忘録として残す。
認証と認可
認証(Authentication)
- 認証とは、ユーザーが「誰であるか」を確認するプロセス。
- 一般的にユーザー名とパスワードの組み合わせで認証を行うが、セキュリティ質問や顔認証なども組み合わせ可能。
- 安全にデータベースに保存することが重要
認可(Authorization)
- ユーザーが「何ができるか」を確認するプロセス。
- ユーザー認証が終わったあとに、認可が行われるのが一般的
- (例)あなたが管理者であることが認証されたから、投稿削除・ユーザー削除できるよみたいなイメージ
パスワード管理方法
1. パスワードはそのまま保存するな!
- パスワードは他のサイトでも同じものを使っているか可能性が高いため、悪用が危ない。
- ハッシュ化(ハッシュ関数をかける)を通して、DBに保存するのが重要。
ハッシュ関数
- 任意のサイズの入力データを固定サイズの出力値に変換できる関数。
- 特定の入力に対しては同じ値が出来上がるので、ログイン時のパスワードにハッシュ関数を通して、DB内のパスワード(ハッシュ後)と比較して一致するかチェックする。
暗号的ハッシュ関数
- 1方向性のハッシュ関数の場合、ハッシュ化された値から元の値に戻せない性質がある
- 入力値がわずかに変化したとしても、出力値は大きく異なる
- 同じ入力からは、必ず同じ出力
- 異なる入力から同じ出力が生成される可能性は、極めて低い
- 関数実行が意図的に遅い
- 高速なハッシュ関数の場合、悪意のある攻撃者が攻撃しまくれるため
ソルトについて
前提として、全く同じパスワードを使っているユーザーがたくさんいる。
その場合、ハッシュ関数にはハッシュ化後の値からもとの値を計算する逆引き辞典を作っている可能性がある。その対策としてソルト
がある。
ソルトの特徴
- ハッシュ化する前にパスワードを加えるランダムな値。前後など
- ほかでは容易に作られない一意なハッシュを保証し、セキュリティ攻撃の軽減につなげる
bcrypt
いろんな言語で使用されるハッシュ化関数。
- ソルト生成とハッシュ化
const bcrypt = require("bcrypt");
const hashPassword = async (password) => {
const salt = await bcrypt.genSalt(16);
const hash = await bcrypt.hash(password, salt);
};
// 下記のようにシンプルに書ける(第2引数にround数をセット)
const hashPassword = async (password) => {
const hash = await bcrypt.hash(password, 16);
};
hashPassword("123456");
- パスワードとハッシュ化パスワードの比較
const login = async (password, hashedPassword) => {
const result = await bcrypt.compare(password, hashedPassword);
if (result) {
console.log("ログイン成功!!!");
} else {
console.log("ログイン失敗!");
}
};
login("123456", "123456をハッシュ化された値") // ログイン成功!!!
Passport
- Node.jsの認証ミドルウェア
- ExpressベースのWebアプリに組み込み可能
- ユーザー名とパスワード、Facebook、Twitterなどを使用した認証をサポート