通常、WebSocketの中で、認証(authorization)情報の追加は、ハンドシェイクや接続確立後に行われ、HTTPリクエストヘッダーのようなメカニズムで渡しています。本文では、WebSocketのリクエストヘッダーに認証情報を追加して、APIのセキュリティを向上する方法を皆さんに紹介します。
WebSocketでの認証ヘッダーについて
WebSocket ハンドシェイク段階で、または接続の確立後に、送受信メッセージ時に、HTTPスタイルの認証ヘッダー(Authorization Header)を使用して認証情報を渡します。WebSocketの認証ヘッダーの基本的な流れは以下の通りです。
(1)ハンドシェイク段階: WebSocket通信はハンドシェイクから始まります。ハンドシェイク処理中、クライアントとサーバーの間でHTTPヘッダーなどの特定の情報が受け渡されます。この段階で、HTTPの認証ヘッダーようなメカニズムを使用して認証情報を転送できます。
(2)Authorization Header(認証ヘッダー): 通常、HTTP認証ヘッダーには認証タイプと資格情報の文字列が含まれ、スペースで区切られています。例えば、基本的な認証用Authorization Headerは次のようになります。
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
上記の例では、"Basic"が認証タイプ、それに続く文字列がBase64エンコードされたユーザー名とパスワードの組み合わせです。
(3)カスタム認証ヘッダー: 基本認証以外に、特定の認証要件を満たすために独自の認可ヘッダーフォーマットを定義することもできます。例えば、次のような形式を使用できます。
Authorization: Bearer your_access_token
この場合、"Bearer"が認証タイプで、後続の文字列がアクセストークンで、ユーザーの身元を確認するために使用されます。
WebSocketの認証ヘッダーの利用シーン
オンラインチャット、リアルタイムのコラボレーション、通知など、多くのリアルタイムアプリケーションでWebSocketを使用して双方向通信を行うのが一般的です。アプリケーションが秘密データを扱う場合やユーザー認証が必要な場合、WebSocketの認証が非常に重要なことになります。こうすると、許可されたユーザーのみがWebSocketサーバーとの接続を確立できることが保証されるので、セキュリティが保証されます。
WebSocket認証を行う一般的な方法
WebSocket認証を行う必要がある場合は、それを実現する方法はたくさんあります。次は、WebSocketの認証を行うために、ユーザーによく使われる一般的な方法を皆さんに紹介します。
方法1: 標準のHTTPヘッダーの使用
WebSocketのハンドシェイク段階はHTTPプロトコルを使用するため、WebSocketのHTTPリクエストヘッダにAuthorizationフィールドを追加できます。サンプルコードは次のとおりです。
const socket = new WebSocket('wss://example.com/socket');
socket.addEventListener('open', (event) => {
// ハンドシェイク段階でAuthorizationヘッダーを追加
socket.send('Authorization: Bearer ' + YOUR_TOKEN);
});
socket.addEventListener('message', (event) => {
// 受信メッセージを処理
console.log('Received:', event.data);
});
方法2: カスタムWebSocketサブプロトコルの使用
カスタムWebSocketサブプロトコルを使用することで、ハンドシェイクリクエストでAuthorization情報を定義できます。これには、サーバー側とクライアント側の両方が対応するサブプロトコルをサポートする必要があります。サンプルコードは次のとおりです。
const socket = new WebSocket('wss://example.com/socket', 'custom-protocol');
socket.addEventListener('open', (event) => {
// ハンドシェイク段階でカスタムプロトコルを介してAuthorization情報を送信
socket.send('Authorization: Bearer ' + YOUR_TOKEN);
});
socket.addEventListener('message', (event) => {
// 受信メッセージを処理
console.log('Received:', event.data);
});
方法3: URLパラメータの使用
WebSocketの接続URLに直接Authorization情報を含めることで、いくつかのシンプルなシナリオに適したシンプルかつ直接的な方法です。 サンプルコードは次のとおりです。
const socket = new WebSocket('wss://example.com/socket?authorization=' + YOUR_TOKEN);
socket.addEventListener('message', (event) => {
// 受信メッセージを処理
console.log('Received:', event.data);
});
方法4: WebSocket拡張機能の使用
一部のWebSocketライブラリは、拡張機能を使用してAuthorization情報を運ぶことをサポートしています。これは通常、WebSocketの初期化段階で適切な設定が必要です。 サンプルコードは次のとおりです。
const socket = new WebSocket('wss://example.com/socket', ['authorization']);
socket.addEventListener('open', (event) => {
// 初期化段階でAuthorization情報を追加
socket.send('Authorization: Bearer ' + YOUR_TOKEN);
});
socket.addEventListener('message', (event) => {
// 受信メッセージを処理
console.log('Received:', event.data);
});
ベストプラクティス:WebSocket認証の実践
このケースでは、標準のHTTPヘッダーを使用して、WebSocketリクエストヘッダーにAuthorization情報を追加する方法を紹介します。仮にサーバー側がWebSocketハンドシェイク時に渡されたJWTトークンを検証しようとしています。
まず、WebSocketサーバーと、認証に使用するJWTトークンが必要です。
// サーバー側の例(Node.js)
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 3000 });
server.on('connection', (socket) => {
// 接続確立時にAuthorizationヘッダーを検証
socket.on('message', (message) => {
if (message.startsWith('Authorization: Bearer')) {
// 認証ロジックを実行し、JWTトークンの有効性をチェック
const token = message.split(' ')[2];
if (validateToken(token)) {
// 認証成功、ビジネスロジックを処理
socket.send('Authentication successful!');
} else {
// 認証失敗、接続を終了
socket.terminate();
}
}
});
});
次に、クライアントの例です。ApidogなどのGUIのAPIクライアントを使用してリクエストを送信することもできます。
// クライアント例(ブラウザでJavaScriptを使用)
const socket = new WebSocket('ws://localhost:3000');
socket.addEventListener('open', (event) => {
// ハンドシェイク段階でAuthorizationヘッダーを追加
socket.send('Authorization: Bearer ' + YOUR_JWT_TOKEN);
});
socket.addEventListener('message', (event) => {
// 受信メッセージを処理
console.log('Received:', event.data);
});
YOUR_JWT_TOKEN
を実際のJWTトークンに置き換える必要があります。
上記のケースでは、標準のHTTPヘッダーを使用してWebSocketリクエストヘッダーにAuthorization情報を追加して、接続確立時の認証にこの情報が使用される方法を解説しました。実際のアプリケーションでは、より複雑な認証ロジックとエラー処理が必要になる場合があります。
WebSocketテストツールを活用
一般的には、WebSocketのAPIが正確に動作できることを保証するために、それをテストする必要があります。そこで、強力的なAPIテストツールが役立ちます。
Apidogは、HTTP、WebSocket、Socket、gRPCなど、さまざまなプロトコルを採用したAPIにも対応できます。APIテスト用定番ツールのPostmanよりも強力なツールにもなるのでしょう。
ApidogでWebSocket APIをテストする
ステップ⒈WebSocketのリクエストを作成
ApidogでWebSocket APIをテストしたい場合、まずはWebSocketのリクエストを作成して、URL、メッセージなどの各パラメータを記入する必要があります。

ステップ⒉メッセージを送信
メッセージタブでは、サーバーに送信したいメッセージを記入することができます。送信ボタンをクリックすると、サーバーが当該メッセージを受信できます。

ステップ⒊パラメータの渡し
通信中に、クリエパラメータをアドレスに追加することでそのパラメータを渡すこともできます。渡せるデータ型には、文字列、整数、数字、配列が含まれており、これらのデータを成功に渡すと、サーバーはこれらのデータ型を受信できます。

ステップ⒋リクエストの保存
リクエストの設定が終わると、「保存」ボタンをクリックして、当該リクエストを保存できます。

ステップ⒌WebSocketサーバーに接続
「接続」ボタンをクリックして、WebSocketサーバーに接続します。

ApidogはWebSocketサーバーへの接続に成功した場合、提示メッセージが返されます。

ステップ⒍WebSocketのリクエストを送信
「送信」ボタンをクリックして、メッセージとパラメータをWebSocketサーバーに送信できます。

ステップ⒎WebSocketサーバーとの通信
リクエストを送信した後、サーバーからメッセージを受信することもできます。例えば、サーバー側が秒単位でクライアントにタイムスタンプを送信することができます。

ステップ⒏WebSocketサーバーとの接続を切断
WebSocketサーバーから接続を切断したい場合、「切断」ボタンをクリックします。

接続が成功に切断された場合、Apidogで提示メッセージが表示されます。

まとめ
この記事では、WebSocketのリクエストヘッダーに認証情報を追加し、APIのセキュリティを高める方法について解説しました。WebSocketでは、ハンドシェイク時やメッセージ送受信時にHTTPのAuthorizationヘッダーのようなメカニズムで認証情報を渡せます。標準のHTTPヘッダー、カスタムサブプロトコル、URLパラメータ、拡張機能など、様々な方法で認証情報を追加できます。ベストプラクティスとして、JWTトークンをハンドシェイク時に渡し、サーバーで検証する例を紹介しました。
ApidogなどのWebSocketテストツールを使えば、簡単にWebSocket APIをテストでき、認証が意図した通りに機能しているか確認できます。WebSocketを使ったアプリケーションの認証やセキュリティ実装の参考になれば幸いです。ぜひこの記事の方法をAPI開発に取り入れてみてください。