AWS WebSocket API GatewayのLambda オーソライザーをCloudFormationで実装する完全ガイド

2025年3月26日

📡 WebSocket APIとは?

従来のREST APIとは異なり、双方向通信が可能なプロトコルです。

REST API: リクエスト→レスポンスの一方通行
WebSocket API: 双方向通信が可能!

WebSocket APIには特徴的なルートがあります:

  • $connect - 接続時に呼び出されるルート
  • $disconnect - 切断時に呼び出されるルート
  • $default - 他のルートに一致しない場合のルート
  • カスタムルート - 独自定義のルート
認証は主に$connectルートで行われます!

🛡️ Lambda オーソライザーとは

APIへのアクセスを制御するための仕組みです。リクエストが来ると、API GatewayはLambda関数を呼び出して認証処理を行います。

1. クライアント接続要求

トークンやAPIキーなどの認証情報付き

2. Lambda オーソライザー呼び出し

認証情報を検証

3. IAMポリシー返却

Allow/Denyを決定

4. 接続許可/拒否

認証結果に基づき処理

WebSocketでの特徴:
$connectルートでのみ使用可能
✅ パス変数は使用できない
✅ methodArnの形式が異なる
✅ requestContextの内容も異なる

🧩 CloudFormationの基本要素

CloudFormationは、AWSリソースをコードとして管理できるサービスです。WebSocket API実装に必要な主要リソース:

  • AWS::ApiGatewayV2::Api - WebSocket API自体
  • AWS::ApiGatewayV2::Route - 各ルート定義
  • AWS::ApiGatewayV2::Integration - バックエンド接続
  • AWS::ApiGatewayV2::Deployment - デプロイメント
  • AWS::ApiGatewayV2::Stage - ステージ管理
基本的なAPI定義
WebSocketApiGateway:
  Type: AWS::ApiGatewayV2::Api
  Properties:
    Name: my-websocket-api
    ProtocolType: WEBSOCKET
    RouteSelectionExpression: "$request.body.action"

RouteSelectionExpressionはメッセージのルーティングに使われる式です。

🔨 Lambda オーソライザー実装手順

STEP 1: オーソライザー関数作成

認証ロジックを実装したLambda関数

STEP 2: 実行権限設定

API GatewayからLambda呼び出しの権限

STEP 3: オーソライザーリソース定義

AWS::ApiGatewayV2::Authorizerリソース

STEP 4: $connectルートに関連付け

AuthorizationType: CUSTOMで設定

オーソライザー定義
WebSocketAuthorizer:
  Type: AWS::ApiGatewayV2::Authorizer
  Properties:
    Name: websocket-authorizer
    ApiId: !Ref WebSocketApiGateway
    AuthorizerType: REQUEST
    AuthorizerUri: !Sub "arn:aws:..."
    IdentitySource:
      - "route.request.querystring.token"

🧠 オーソライザー関数の中身

オーソライザー関数は、リクエストから認証情報を取得して検証し、IAMポリシーを返します。

Node.js実装例
exports.handler = async (event) => {
  // 認証情報を取得
  const queryParams = event.queryStringParameters || {};
  const token = queryParams.token;

  // 検証ロジック
  if (token !== 'valid-token') {
    return {
      principalId: 'unknown',
      policyDocument: {
        Version: '2012-10-17',
        Statement: [{
          Action: 'execute-api:Invoke',
          Effect: 'Deny',
          Resource: event.methodArn
        }]
      }
    };
  }

  // 認証成功
  return {
    principalId: 'user123',
    policyDocument: { ... Effect: 'Allow' ... }
  };
}
ポイント:
principalId: 認証されたユーザーのID
Effect: 'Allow'/'Deny'でアクセス制御

🔌 $connectルートの設定

$connectルートにオーソライザーを関連付けることで、接続時に認証が行われます。

$connectルート定義
ConnectRoute:
  Type: AWS::ApiGatewayV2::Route
  Properties:
    ApiId: !Ref WebSocketApiGateway
    RouteKey: $connect
    AuthorizationType: CUSTOM
    AuthorizerId: !Ref WebSocketAuthorizer
    Target: !Sub "integrations/${ConnectIntegration}"
ここがポイント!
AuthorizationType: CUSTOMとAuthorizerIdを設定することで、カスタムオーソライザーを使用できます。

オーソライザーは$connectルートでのみ使用可能であることに注意してください。一度接続が確立されると、その後のメッセージに対しては認証が行われません。

🔗 接続URLの形式

WebSocketの接続URLに認証情報を含める場合、以下のような形式になります:

接続URL例
wss://xxxx.execute-api.ap-northeast-1.amazonaws.com/prod?token=valid-token
ブラウザからの制約:
JavaScriptのWebSocket APIでは、HTTPヘッダーを操作できないため、ヘッダーベースの認証が使えません。ブラウザからの接続ではクエリパラメータを使用することが一般的です。

接続処理の流れ:

  • クライアントが上記URLで接続を試みる
  • API Gatewayが$connectルートを処理
  • オーソライザーが呼び出され、tokenを検証
  • 認証結果に基づいて接続許可/拒否

🚀 自動デプロイの設定

CloudFormationスタックを更新する際に、自動的にAPI Gatewayがデプロイされるように設定できます。

ステージ設定
Stage:
  Type: AWS::ApiGatewayV2::Stage
  Properties:
    ApiId: !Ref WebSocketApiGateway
    StageName: prod
    # DeploymentIdは指定しない
    AutoDeploy: true
AutoDeploy: trueを設定することで、ルートやインテグレーションを変更するたびに自動的にデプロイされます。

オーソライザーをテストするには、新しい接続を作成する必要があります。既存の接続に対して$connectオーソライザーを変更しても影響はありません。

🔒 セキュリティベストプラクティス

  • 強力な認証メカニズムの使用
    JWTやAWS Cognitoなどを活用しましょう。
  • 多要素認証の採用
    可能であれば、追加の認証要素(MFA)を取り入れましょう。
  • レート制限の実装
    ブルートフォース攻撃を防ぐために、接続試行回数を制限しましょう。
  • 通信の暗号化
    必ずwss://(WebSocket Secure)プロトコルを使用しましょう。
  • 入力検証とサニタイズ
    オーソライザー関数内で、すべての入力を厳密に検証しましょう。
セキュリティは常に最優先事項です!
特にリアルタイム通信では、継続的な接続を悪用されるリスクがあります。