メインコンテンツへスキップ

ヘルプセンター

API認証・セキュリティガイド

最終更新: 2024/1/17
apiauthenticationoauthjwtsecuritybest-practices
API認証・セキュリティガイド 築古不動産投資シミュレーターのAPIは、企業レベルのセキュリティ要件を満たすOAuth 2.0認証を採用しています。このガイドでは、認証フローから実装まで、セキュリティのベストプラクティスを詳しく解説します。 🔐 認証システム概要 OAuth 2.0:業界標準の認証プロトコル Multiple Providers:Google、GitHub、Microsoft対応 JWT Tokens:ステートレスなトークン管理 Refresh Tokens:長期間のセッション維持 Scope-based Access:細かい権限制御 Rate Limiting:DoS攻撃の防止 🔄 OAuth 2.0 認証フロー詳細 📋 Authorization Code Flow 最も安全な認証フローで、サーバーサイドアプリケーションに推奨されます。 1. 認証URL生成 GET https://kominka-apart-sim.vercel.app/auth/oauth/authorize? response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=https://your-app.com/callback& scope=read:simulations write:simulations& state=RANDOM_STATE_STRING 2. ユーザー認証 ユーザーはプロバイダー(Google/GitHub)で認証を行います。 3. 認証コード取得 GET https://your-app.com/callback? code=AUTHORIZATION_CODE& state=RANDOM_STATE_STRING 4. アクセストークン交換 POST https://kominka-apart-sim.vercel.app/auth/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& code=AUTHORIZATION_CODE& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRET& redirect_uri=https://your-app.com/callback 5. トークンレスポンス { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "scope": "read:simulations write:simulations", "user_id": "123e4567-e89b-12d3-a456-426614174000" } 🔒 Client Credentials Flow サーバー間通信やMCPサーバー用の認証フローです。 トークン取得 POST https://kominka-apart-sim.vercel.app/auth/oauth/token Content-Type: application/x-www-form-urlencoded Authorization: Basic BASE64(client_id:client_secret) grant_type=client_credentials& scope=mcp:tools calculation:realtime レスポンス { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 7200, "scope": "mcp:tools calculation:realtime" } 🎫 JWT トークンの詳細 JWT構造 JWTは3つの部分で構成されています: Header { "alg": "RS256", "typ": "JWT", "kid": "key-id-2024" } Payload { "iss": "https://kominka-apart-sim.vercel.app", "sub": "123e4567-e89b-12d3-a456-426614174000", "aud": "kominka-api", "exp": 1642694400, "iat": 1642690800, "scope": "read:simulations write:simulations", "user_email": "user@example.com", "user_name": "田中太郎", "plan": "premium" } Signature RS256( base64UrlEncode(header) + "." + base64UrlEncode(payload), private_key ) JWT検証 受信したJWTは以下の手順で検証します: 署名検証:公開鍵を使用してRS256署名を検証 有効期限チェック:expクレームを確認 発行者確認:issクレームが正しいか確認 オーディエンス確認:audクレームが一致するか確認 🔄 トークンリフレッシュ 自動リフレッシュの実装 JavaScript実装例 class AuthManager { constructor(clientId, clientSecret) { this.clientId = clientId; this.clientSecret = clientSecret; this.accessToken = null; this.refreshToken = null; this.expiresAt = null; } async getValidToken() { // トークンの有効期限をチェック(余裕をもって5分前) if (this.expiresAt && Date.now() Python実装例 import time import requests from datetime import datetime, timedelta class AuthManager: def __init__(self, client_id, client_secret): self.client_id = client_id self.client_secret = client_secret self.access_token = None self.refresh_token = None self.expires_at = None self.base_url = "https://kominka-apart-sim.vercel.app" def get_valid_token(self): # トークンの有効期限をチェック if self.expires_at and datetime.now() 🔒 セキュリティベストプラクティス ⚠️ 重要なセキュリティ対策 1. クライアントシークレットの保護 環境変数:機密情報は環境変数で管理 サーバーサイドのみ:フロントエンドにシークレットを含めない 定期的な更新:90日ごとにシークレットをローテーション 2. トークンストレージ HttpOnly Cookie:XSS攻撃を防ぐため Secure Flag:HTTPS通信でのみ送信 SameSite属性:CSRF攻撃を防ぐため 3. HTTPS通信 TLS 1.2以上:暗号化通信の強制 Certificate Pinning:中間者攻撃の防止 HSTS:HTTP Strict Transport Security 4. 入力値検証 スキーマ検証:JSONスキーマによる厳格な検証 SQLインジェクション対策:パラメータ化クエリ XSS対策:入力値のサニタイゼーション 🛡️ 高度なセキュリティ機能 🔍 異常検知とモニタリング 1. 不審なアクセスパターン検知 レート制限超過:短時間の大量リクエスト 地理的異常:通常とは異なる地域からのアクセス デバイス異常:新しいデバイスからのアクセス 2. セキュリティヘッダー // 推奨セキュリティヘッダー const securityHeaders = { 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'", 'Permissions-Policy': 'geolocation=(), microphone=(), camera=()' }; 3. APIレスポンスの匿名化 // 機密情報のマスキング { "user_id": "123e4567-****-****-****-426614174000", "email": "user@******.com", "api_key": "ak_****...****", "simulation_data": { // 実際のデータ } } 🔧 実装例とコードサンプル 🚀 Complete Authentication Client React Hooks実装 import { useState, useEffect, useContext, createContext } from 'react'; const AuthContext = createContext(); export const useAuth = () => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within AuthProvider'); } return context; }; export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [accessToken, setAccessToken] = useState(null); useEffect(() => { // ページ読み込み時の認証状態確認 checkAuthStatus(); }, []); const checkAuthStatus = async () => { try { const response = await fetch('/api/auth/me', { credentials: 'include' // HttpOnly cookieを送信 }); if (response.ok) { const userData = await response.json(); setUser(userData); setAccessToken(userData.access_token); } } catch (error) { } finally { setLoading(false); } }; const login = (provider = 'google') => { const authUrl = `https://kominka-apart-sim.vercel.app/auth/oauth/authorize?` + new URLSearchParams({ response_type: 'code', client_id: process.env.NEXT_PUBLIC_CLIENT_ID, redirect_uri: `${window.location.origin}/auth/callback`, scope: 'read:simulations write:simulations', state: generateRandomState(), provider: provider }); window.location.href = authUrl; }; const logout = async () => { try { await fetch('/api/auth/logout', { method: 'POST', credentials: 'include' }); setUser(null); setAccessToken(null); } catch (error) { } }; const apiCall = async (endpoint, options = {}) => { const response = await fetch(`/api${endpoint}`, { ...options, headers: { ...options.headers, 'Authorization': accessToken ? `Bearer ${accessToken}` : undefined }, credentials: 'include' }); if (response.status === 401) { // 認証エラーの場合は再ログインを促す setUser(null); setAccessToken(null); throw new Error('認証が必要です'); } return response; }; const generateRandomState = () => { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); }; const value = { user, loading, login, logout, apiCall, isAuthenticated: !!user }; return ( {children} ); }; Node.js Express Middleware const jwt = require('jsonwebtoken'); const rateLimit = require('express-rate-limit'); // JWT検証ミドルウェア const authenticateJWT = (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: 'Authorizationヘッダーが必要です' }); } const token = authHeader.substring(7); try { const decoded = jwt.verify(token, process.env.JWT_PUBLIC_KEY, { algorithms: ['RS256'], issuer: 'https://kominka-apart-sim.vercel.app', audience: 'kominka-api' }); req.user = decoded; next(); } catch (error) { if (error.name === 'TokenExpiredError') { return res.status(401).json({ error: 'トークンの有効期限が切れています' }); } return res.status(403).json({ error: '無効なトークンです' }); } }; // レート制限ミドルウェア const createRateLimit = (windowMs, max, message) => { return rateLimit({ windowMs, max, message: { error: message }, standardHeaders: true, legacyHeaders: false, handler: (req, res) => { res.status(429).json({ error: 'レート制限に達しました', retryAfter: Math.ceil(windowMs / 1000) }); } }); }; // API用レート制限 const apiRateLimit = createRateLimit( 60 * 60 * 1000, // 1時間 1000, // 1000リクエスト 'API制限に達しました。1時間後に再試行してください。' ); // 計算API用レート制限 const calculationRateLimit = createRateLimit( 60 * 60 * 1000, // 1時間 500, // 500リクエスト '計算API制限に達しました。1時間後に再試行してください。' ); module.exports = { authenticateJWT, apiRateLimit, calculationRateLimit }; 🔍 セキュリティ監査とコンプライアンス 🏆 セキュリティ認証 SOC 2 Type II:セキュリティ統制の監査済み ISO 27001:情報セキュリティ管理システム GDPR準拠:EU一般データ保護規則 個人情報保護法:日本の個人情報保護法準拠 セキュリティ監査ログ // セキュリティイベントの記録 { "timestamp": "2024-01-17T10:30:00Z", "event_type": "authentication_success", "user_id": "123e4567-e89b-12d3-a456-426614174000", "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0...", "location": { "country": "Japan", "city": "Tokyo" }, "risk_score": 0.1, "additional_data": { "provider": "google", "session_duration": 3600 } } 🔗 関連リンク MCP Server完全セットアップガイド エンドポイント詳細リファレンス API完全ガイド OAuth 2.0 仕様 JWT.io - JWT デバッガー

この記事は役に立ちましたか?