Node.jsとReactにおけるトークン認証(Token Authentication)は、ウェブアプリケーションのセキュリティを強化するための非常に重要な方法です。特に、ユーザー認証に関連する操作を行う際、ユーザーのプライバシーとデータの保護が求められます。本記事では、Node.jsバックエンドとReactフロントエンドを使用して、トークン認証を完全かつ包括的に実装する方法について説明します。
トークン認証とは?
トークン認証は、ユーザーがログインした後にサーバーから生成されるトークンを使用して、ユーザーの認証情報を管理する方法です。一般的に、JWT(JSON Web Token)が使用されます。トークンは、認証済みのユーザーであることを証明し、サーバーに対してリクエストを行う際に、セッションを維持するための手段として機能します。

必要な技術とライブラリ
- Node.js:サーバーサイドの実装に使用します。
- Express:Node.jsのウェブフレームワークとして使用します。
- jsonwebtoken:JWTトークンを生成・検証するためのライブラリです。
- bcryptjs:ユーザーのパスワードをハッシュ化するためのライブラリです。
- React:フロントエンドのユーザーインターフェースを作成するために使用します。
- axios:ReactからNode.jsバックエンドへHTTPリクエストを送信するために使用します。
1. Node.jsバックエンドの設定
まず、Node.jsバックエンドのセットアップを行います。
1.1 パッケージのインストール
Node.jsのプロジェクトを作成し、必要なライブラリをインストールします。
bashmkdir myapp
cd myapp
npm init -y
npm install express jsonwebtoken bcryptjs dotenv cors
1.2 サーバーの作成
次に、基本的なExpressサーバーをセットアップします。server.js
というファイルを作成し、以下のコードを追加します。
javascriptconst express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const dotenv = require('dotenv');
const cors = require('cors');
dotenv.config();
const app = express();
const PORT = process.env.PORT || 5000;
// ミドルウェアの設定
app.use(express.json());
app.use(cors());
// ユーザーのサンプルデータ
let users = [
{ id: 1, username: 'user1', password: '$2a$10$7zYJY.Urg1Zvq8Rmg6jH4uMc5XgdKTp7ghdZ0X0f0XUfaH9yWriOe' } // パスワードはハッシュ化された「password123」
];
// JWTの生成
const generateToken = (user) => {
return jwt.sign({ id: user.id, username: user.username }, process.env.JWT_SECRET, { expiresIn: '1h' });
};
// ログインエンドポイント
app.post('/login', async (req, res) => {
const { username, password } = req.body;
// ユーザーの存在確認
const user = users.find(u => u.username === username);
if (!user) {
return res.status(400).json({ message: 'ユーザーが見つかりません' });
}
// パスワードの照合
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: 'パスワードが間違っています' });
}
// JWTの生成
const token = generateToken(user);
res.json({ token });
});
// トークン検証エンドポイント(認証用)
app.get('/protected', (req, res) => {
const token = req.header('Authorization');
if (!token) {
return res.status(401).json({ message: 'トークンが必要です' });
}
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
return res.status(401).json({ message: '無効なトークンです' });
}
res.json({ message: '認証成功', user: decoded });
});
});
app.listen(PORT, () => {
console.log(`サーバーはポート${PORT}で起動しています`);
});
1.3 JWTシークレットの設定
.env
ファイルを作成し、JWTのシークレットキーを設定します。
iniJWT_SECRET=your_secret_key
2. Reactフロントエンドの設定
次に、Reactを使用してユーザーインターフェースを作成します。
2.1 Reactアプリの作成
Reactのプロジェクトを作成し、必要なパッケージをインストールします。
bashnpx create-react-app myapp-client
cd myapp-client
npm install axios
2.2 ログインフォームの作成
src/App.js
に以下のコードを追加して、ユーザーがログインするためのフォームを作成します。
javascriptimport React, { useState } from 'react';
import axios from 'axios';
function App() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [token, setToken] = useState('');
const [message, setMessage] = useState('');
const handleLogin = async () => {
try {
const response = await axios.post('http://localhost:5000/login', { username, password });
setToken(response.data.token);
setMessage('ログイン成功');
} catch (error) {
setMessage(error.response.data.message);
}
};
const fetchProtectedData = async () => {
try {
const response = await axios.get('http://localhost:5000/protected', {
headers: { Authorization: token }
});
setMessage(response.data.message);
} catch (error) {
setMessage(error.response.data.message);
}
};
return (
<div>
<h1>ログインh1>
<input
type="text"
placeholder="ユーザー名"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<input
type="password"
placeholder="パスワード"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button onClick={handleLogin}>ログインbutton>
{token && <button onClick={fetchProtectedData}>保護されたデータを取得button>}
<p>{message}p>
div>
);
}
export default App;
2.3 トークンの保存と使用
ログイン成功後、JWTトークンはReactアプリの状態として保存され、その後、保護されたエンドポイントにアクセスするために使用されます。上記のコードでは、token
状態を使ってトークンを管理し、HTTPリクエストのAuthorizationヘッダーにトークンを添付しています。
3. セキュリティの強化
トークン認証のセキュリティを強化するために、以下の点を考慮することが重要です。
- HTTPSを使用する:トークンを暗号化して送受信するために、HTTPS(SSL/TLS)を使用することを強くお勧めします。
- トークンの有効期限を設定する:JWTは有効期限を設定することで、長期間使用されることを防ぎます。
- リフレッシュトークンの使用:トークンが期限切れになった場合に、リフレッシュトークンを使用して新しいトークンを取得できる仕組みを導入することが推奨されます。
まとめ
Node.jsとReactを使用したトークン認証の実装は、ユーザーのセキュリティとプライバシーを守るために不可欠です。JWTを利用することで、セッション管理が簡素化され、保護されたリソースへのアクセスを効率的に制御できます。この記事では、バックエンドとフロントエンドの両方の実装方法を示しましたが、実際のプロジェクトに応じて、さらなるセキュリティ強化やエラーハンドリングを追加することが重要です。