はじめに
こんにちは。京都大学大学院情報学研究科 修士1年生の有泉洵平です。
2021 年度 技術職 就業型コースのインターンシップに 8/16 から 9/24 までの期間で参加し、開発 4 センターという組織の中で、主に LINE Login や LINE Front-end Framework (LIFF), LINE Things/Beacon, LINE Developer Center を開発している Developer Product Team 2 に所属して開発を行なっていました。
インターンシップ中、私は LINE Login の機能追加・改善に取り組みました。
LINE Login とは
LINE Login とは、LINE が開発している Social Login Service のことです。
LINE が保有するユーザデータなどを安全に外部に提供するために、OAuth 2.0 と OpenID Connect 1.0 に準拠していて、社外向けには Authorization Code Flow を提供しています。
また、LINE Login には独自機能として、QR Code を読み取ることで ID/password なしでログインすることができる QR Code Loginや、スマートフォン上のブラウザで web サイトに自動でログインすることができる Auto Login といった便利な機能も実装されています。

Authorization Code Flow
Authorization Code Flow とは、以下のようなやり取りを行なって、ユーザー情報などの resource を取得するための token をクライアントが Authorization Server から受け取る仕組みのことです。

- ユーザは、クライアントに認可プロセスを開始するように伝えます。
- クライアントは、Authorization Server の Authorization endpoint に必要なパラメータを付けてリダイレクトします。このリクエストを Authorization Request といいます。
- Authorization endpoint は、ログインフォームや同意画面をユーザに表示し、認証認可を行います。
- Authorization endpoint は、クライアントに Authorization Code などを付けてリダイレクトします。このレスポンスを Authorization Response といいます。
- state を検証します。
- クライアントは、Authorization Code を用いて、Authorization Server の Token endpoint に token を要求します。
- Token endpoint は クライアントに token を返します。
JWT Secured Authorization Response Mode (JARM) の実装
インターン中に行った 1 つ目のタスクは、Financial-grade API (FAPI) で定義されている JWT Secured Authorization Response Mode (JARM) を LINE Login に実装するというものでした。
背景
攻撃者が A さんの Authorization Code を何かしらの方法で取得した場合を考えます。
4 のリダイレクト時に Authorization Response 内の Authorization Code を A さんのものと入れ替えると、攻撃者は A さんの token を取得することができてしまいます。
また、Authorization Code 以外にも、state などを改ざんすることもできてしまいます。
そして、何も対策をしなければ、Authorization Response の改ざんをクライアントは検知することができません。

このような問題を解決するために考えられた方法の 1 つが、JARM です。
JARM とは
JARM とは、Authorization Response として、Authorization Code や state を claim に含んだ JWT を返すという仕様です。
クライアントは、JWT の署名検証をすることで、Authorization Response の改ざんを検知することができます。
JARM は、Authorization Request の response_mode パラメータに、以下の値を選択することで利用することができます。
- query.jwt
- form_post.jwt
- fragment.jwt (*LINE Login では、Authorization Code Flow しか提供していないため、未対応)
- jwt

throttling の実装
インターン中に行った 2 つ目のタスクは、 LINE Login に throttling を実装するというものでした。
背景
何らかのキャンペーンやイベントが開催されるなどで、LINE Login サーバへのリクエストが急激に増えてしまう場合があります。
想定していた以上のリクエストを受け付けてしまうと、リクエストを処理しきれず、サーバが落ちてしまう可能性があります。
このような問題を解決するために、LINE Login サーバに throttling の機能を追加します。
仕組み
Java EE の servlet filter を用いて、以下のように throttling 機能を実装しました。

- クライアントから送られてきたリクエストは、Filter を通ります。
- Filter では、リクエスト数をインクリメントします。
- リクエスト数が上限値を超えていないかを確認します。
- 上限値を超えていれば、その段階でリクエストを拒否します。
- 上限値を超えていなければ、Controller にリクエストを送ります。
- Controller で必要な処理を行います。
- レスポンスをクライアントに返します。
実装のポイント
リクエスト数の上限値をソースコード中に書いたり、環境変数から読み取る仕様にしてしまうと、その値を変更したい場合にアプリケーションを再起動しなければなりません。
理想的なリクエスト数の上限値は、時と場合により変化するため、アプリケーションの再起動なしに気軽に変更できるような仕組みが求められます。
そこで、LINE が管理している OSS の CentralDogma を用いることで、アプリケーションの再起動なしで動的に値を変更できるようにしました。
データプラットフォームに送信するログの制御
インターン中に行った 3 つ目のタスクは、LINE Login サーバからデータプラットフォームに送信するログを制御するというものでした。
背景
LINE には、Information Universe (IU) というデータプラットフォームがあります。
IU にログを送っておくことで、障害対応時などにログの調査分析や集計などが簡単に行えるようになっています。
IU にログを送る構成の一部分を抜き出して簡略化したものが以下の図になります。

IU に送るログの中には、リクエストやレスポンスなどの様々な情報が含まれます。
今回、Elasticsearch (ES) にログとして送っているリクエストヘッダーの種類が多すぎた結果、ES に index が貼れなくなってしまったため、ログとして送るリクエストヘッダーを制限します。
仕組み
ログを送る際に、重要だと思われるリクエストヘッダーだけをフィルタリングし、ES に送るように変更しました。
しかし、重要でないと判断されたリクエストヘッダーの中に実は重要であるものが含まれる場合も考えられるため、全てのリクエストヘッダーを String にしたものも ES に送るようにしました。
あるリクエストヘッダーが重要であるかは、事前にホワイトリストを作成し、その中に含まれているかで判断すればよいですが、完璧なホワイトリストを作成することは難しいため、ここでも CentralDogma を用いて、ホワイトリストの値を動的に変更できるようにしました。
まとめ
今回のインターンシップでは、LINE Login に関する開発を行いました。
LINE Login には、認証認可をセキュアにするために様々な仕組みが実装されていて非常に勉強になった一方、仕様が複雑であったため、コードリーディングや実装が難しく感じました。
また、ソースコードが複数レポジトリに分かれていて別々のチームが担当していたり、古いバージョンの LINE Login との互換性を考える必要があったりと、大規模サービスならではの経験を積むことができました。
その他
インターン中に行った様々なことを紹介します。
夕会
毎日メンターの方々と夕会を行いました。
進捗共有などを行った後、開発に関係することから開発に関係しないことまでをざっくばらんに話しました。
元々は 30 分を想定していたのですが、話したいことが多すぎたため、途中からは 1 時間とってもらっていました。
開発 4 センター 開発現状共有会
LT のような形で、色々な方が発表していました。
あるプロジェクトで得た知見を文章化し、開発 4 センター全体に共有していて、とても良い文化だと思いました。
開発 4 センターに限らず、LINE 全体で知見を文章化する雰囲気が感じられました。
実際、LINE の wiki には様々な知見がまとめられていて、非常に役に立ちました。
インターン生交流会
お昼の時間にインターン生と集まってランチをしました。
リモート勤務ということもあって、普通に開発を行なっていると他のインターン生と交流をすることができないため、非常に良かったです。
人事の方が適当にブレイクアウトルームに振り分けてくれるのですが、前に振り分けてもらったメンバーと全く同じメンバーになった回があって驚いたことは秘密です。
おわりに
6 週間という短くはない期間でしたが、学ぶことが多く、あっという間に感じました。
インターンシップ中に行ったタスクは、どれも私の興味に合ったもので、非常に楽しかったです。
メンターの方々やチームの方々、人事の方々など、ありがとうございました!
LINE のインターンシップに興味のある方はぜひエントリーしてみてください!