3
0

More than 1 year has passed since last update.

React NativeのWebSocketは接続先のホストがOriginに使われる

Last updated at Posted at 2020-12-12

Origin ヘッダー、 CORS とは

ブラウザから JavaScript で別ドメインの API 、画像、音声ファイルなどのリソースを利用するときはもろもろの脆弱性(詳しくは割愛)を防ぐため、 CORS という仕組みを使いリクエストの Origin ヘッダーを見てアクセスを許可する場合のみレスポンスに Access-Control-Allow-Origin ヘッダーを返してあげる必要があります。

オリジン間リソース共有 (CORS)

これはブラウザのセキュリティを担保するためのものなので、ターミナルから curl コマンドを使ったリクエストや Node.js からのアクセスなどには関係ありません。つまり React Native にも基本的には関係ありません。

オリジン間のWebSocket

WebSocket には CORS が適用されないため、 Origin をヘッダーを見て意図しないオリジンからのアクセスを拒否するように WebSocket サーバー内で実装する必要があります。

これをしないと Cross-Site WebSocket Hijacking の危険性があります。

React Native の WebSocket の Origin って?

前述の通り React Native に CORS は基本的には影響しませんが、 WebSocket 接続時のセキュリティを担保するための Origin ヘッダーはどのように設定されているのでしょうか?

ドキュメントには記述が見つけられませんでしたが、 React Native のネイティブ側の WebSocket の実装をみると WebSocketの接続先の ws(s)http(s) に置換した文字列を Origin ヘッダーにセットしているようでした。

iOS
https://github.com/facebook/react-native/blob/v0.63.4/Libraries/WebSocket/RCTSRWebSocket.m#L1552-L1571

Android
https://github.com/facebook/react-native/blob/6e6443afd04a847ef23fb6254a84e48c70b45896/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java#L105-L129

Android の実装をみると JS から Origin ヘッダーが渡された場合その値が使われるようになっていそうですが、 iOS のほうにはそのような挙動はないようなので、 Origin ヘッダーは渡さない方がよさそうな感じがします。

なぜこれが必要だったのか

現在のプロジェクトで Hasura という PostgreSQL から GraphQL API を生成してくれるミドルウェアを使っているのですが、 Hasura には HASURA_GRAPHQL_CORS_DOMAIN 環境変数をセットすることでCORSを許可するドメインを指定できる機能があります。

GraphQL engine server config examples | Hasura GraphQL Docs

HASURA_GRAPHQL_CORS_DOMAIN をセットすると、同時に GraphQL Subscription の WebSocket 接続もその Origin 以外からは弾くようになっています。

Subscriptions | Hasura GraphQL Docs

この仕様は基本的にはありがたいのですが、 React Native の場合は CORS は関係ないはずなのに WebSocket のときのみ接続が弾かれてしまうという問題があり CORS の設定ができないでいました。

React Native からの WebSocket 接続があるときは、 WebSocket サーバー自体のドメインを許可する Origin に追加すればよさそうです。

まとめと宣伝

Hasura の CORS を設定すると WebSocket が接続できなくなる問題があるため Production checklist のうち CORS の設定だけできていなかったのですが、これで一通り実践できるようになりました :tada:

最後に宣伝です。
現在 TypeScript / Next.js / React Native / GraphQL / Hasura を使った開発現場で業務委託やインターンのエンジニアを募集しています。
興味がございましたら shinnoki までご連絡下さい。

3
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0