🔐 認証サービス
認証サービスは、アイデンティティ登録、ログイン、ログアウト、およびJWTベースのセキュリティとCookieサポートによるトークン管理を含む完全な認証システムを提供します。
🚀 クイックスタート
import express from 'express';
import { MongoClient } from 'mongodb';
import {
services,
middlewares,
types
} from '@nodeblocks/backend-sdk';
const client = new MongoClient('mongodb://localhost:27017').db('dev');
express()
.use(
services.authService(
{
identity: client.collection('identity'),
onetimetoken: client.collection('onetimetoken'),
invitations: client.collection('invitations'),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
maxFailedLoginAttempts: 5,
accessTokenExpireTime: '2h',
refreshTokenExpireTime: '2d',
verifyEmailConfig: {
enabled: true,
sender: 'noreply@example.com',
mailService: {
sendMail: async (mailData: types.MailData) => {
console.log(mailData);
return true;
},
},
emailConfig: {
bodyTemplate: 'こんにちは {{email}}',
subject: 'アプリケーションへようこそ',
urlTemplate: 'https://example.com/verify-email?token={{token}}',
},
},
invitation: {
enabled: true,
emailConfig: {
bodyTemplate: '{{organizationName}}への招待',
subject: '組織への招待',
urlTemplate: 'https://example.com/accept-invitation?token={{token}}',
},
},
},
{
sendMail: async (mailData: types.MailData) => {
console.log('メール送信:', mailData);
return true;
},
}
)
)
.use(middlewares.nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('認証サーバーが起動しました'));
📋 エンドポイント概要
メソッド | パス | 説明 | 認証 |
---|---|---|---|
POST | /auth/register | 新規ユーザー登録 | なし |
POST | /auth/login | ユーザーログイン | なし |
POST | /auth/logout | ユーザーログアウト | Bearerトークン必須 |
POST | /auth/refresh-token | アクセストークンをリフレッシュ | Refreshトークン必須 |
POST | /auth/verify-email | メール検証 | なし |
POST | /auth/change-password | パスワード変更 | Bearerトークン必須 |
POST | /auth/forgot-password | パスワードリセット | なし |
POST | /auth/reset-password | パスワードリセット実行 | なし |
🔧 必要な設定
データストア
認証サービスには以下のMongoDBコレクションが必要です:
const dataStores = {
identity: client.collection('identity'), // ユーザー認証情報
onetimetoken: client.collection('onetimetoken'), // ワンタイムトークン
invitations: client.collection('invitations'), // 招待状(オプション)
};
設定オプション
interface AuthConfig {
authSecrets: {
authEncSecret: string; // 暗号化シークレット
authSignSecret: string; // 署名シークレット
};
maxFailedLoginAttempts?: number; // デフォルト: 5
accessTokenExpireTime?: string; // デフォルト: '1h'
refreshTokenExpireTime?: string; // デフォルト: '7d'
verifyEmailConfig?: {
enabled: boolean;
sender: string;
mailService: MailService;
emailConfig: EmailTemplate;
};
invitation?: {
enabled: boolean;
emailConfig: EmailTemplate;
};
}
🔐 認証フロー
1. ユーザー登録
curl -X POST http://localhost:8089/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securePassword123"
}'
レスポンス:
{
"message": "ユーザーが正常に登録されました",
"userId": "uuid-here",
"emailVerificationRequired": true
}
2. メール検証(有効な場合)
curl -X POST http://localhost:8089/auth/verify-email \
-H "Content-Type: application/json" \
-d '{
"token": "verification-token-from-email"
}'
3. ログイン
curl -X POST http://localhost:8089/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securePassword123"
}'
レスポンス:
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"tokenType": "Bearer",
"expiresIn": 3600,
"user": {
"id": "uuid-here",
"email": "user@example.com",
"verified": true
}
}
4. 保護されたリソースへのアクセス
curl -X GET http://localhost:8089/protected-endpoint \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
5. トークンリフレッシュ
curl -X POST http://localhost:8089/auth/refresh-token \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}'
🔒 セキュリティ機能
パスワード要件
- 最小8文字
- 大文字と小文字を含む
- 数字を含む
- 特殊文字を含む
トークンセキュリティ
- アクセストークン: 短期間(デフォルト1時間)
- リフレッシュトークン: 長期間(デフォルト7日)
- ワンタイムトークン: メール検証とパスワードリセット用
ブルートフォース保護
{
maxFailedLoginAttempts: 5, // 5回失敗後アカウントロック
lockoutDuration: '15m', // 15分間のロックアウト
}
📧 メール統合
メール検証設定
verifyEmailConfig: {
enabled: true,
sender: 'noreply@yourapp.com',
mailService: {
sendMail: async (mailData) => {
// メール送信実装
return await yourEmailProvider.send(mailData);
},
},
emailConfig: {
bodyTemplate: `
<h1>メール検証</h1>
<p>こんにちは {{email}} さん</p>
<p>以下のリンクをクリックしてメールアドレスを検証してください:</p>
<a href="{{verificationUrl}}">メールを検証</a>
`,
subject: 'メールアドレスを検証してください',
urlTemplate: 'https://yourapp.com/verify-email?token={{token}}',
},
},
パスワードリセットメール
forgotPasswordConfig: {
emailConfig: {
bodyTemplate: `
<h1>パスワードリセット</h1>
<p>パスワードリセットリクエストを受け取りました。</p>
<p>以下のリンクをクリックして新しいパスワードを設定してください:</p>
<a href="{{resetUrl}}">パスワードをリセット</a>
<p>このリンクは15分間有効です。</p>
`,
subject: 'パスワードリセット',
urlTemplate: 'https://yourapp.com/reset-password?token={{token}}',
},
},
🎯 高度な使用方法
カスタムバリデーション
import { authService } from '@nodeblocks/backend-sdk';
// カスタムユーザーバリデーション
const customAuthConfig = {
...baseConfig,
customValidation: {
emailDomain: '@company.com', // 特定ドメインのみ許可
passwordPolicy: {
minLength: 12,
requireSpecialChars: true,
requireNumbers: true,
},
},
};
複数認証プロバイダー
// OAuth統合の準備
const authConfig = {
...baseConfig,
oauth: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
},
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
},
},
};
セッション管理
// Cookieベース認証
const cookieConfig = {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000, // 24時間
};
🔧 カスタマイゼーション
エラーメッセージのカスタマイズ
const customMessages = {
invalidCredentials: '無効なメールアドレスまたはパスワードです',
accountLocked: 'アカウントがロックされています。しばらくしてから再試行してください',
emailNotVerified: 'メールアドレスが検証されていません',
tokenExpired: 'トークンの有効期限が切れています',
};
レート制限
import rateLimit from 'express-rate-limit';
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分
max: 5, // 15分間に5回までのログイン試行
message: 'ログイン試行回数が上限に達しました',
});
app.use('/auth/login', authLimiter);
🧪 テスト
ユニットテスト例
import { authService } from '@nodeblocks/backend-sdk';
import { createMemoryDataStore } from '../test-utils';
describe('認証サービス', () => {
let authApp;
let testDataStore;
beforeEach(() => {
testDataStore = createMemoryDataStore();
authApp = authService(
{
identity: testDataStore.collection('identity'),
onetimetoken: testDataStore.collection('onetimetoken'),
},
testConfig
);
});
test('ユーザー登録が成功する', async () => {
const response = await request(authApp)
.post('/auth/register')
.send({
email: 'test@example.com',
password: 'SecurePass123!',
})
.expect(201);
expect(response.body.message).toBe('ユーザーが正常に登録されました');
});
test('無効なメールアドレスを拒否する', async () => {
await request(authApp)
.post('/auth/register')
.send({
email: 'invalid-email',
password: 'SecurePass123!',
})
.expect(400);
});
});
🔗 関連リソース
➡️ 次のステップ
認証サービスを設定したら、ユーザーサービスと統合してユーザー管理機能を追加することを検討してください。