フューチャー技術ブログ

Auth0のトークン取得とITPへの対応

はじめに

こんにちは。フューチャーの棚井龍之介と申します。認証認可連載の 4 本目を担当しました。

認証認可周りは最近触りたてでして、普段の開発業務では、Go・React・AWS を利用しています。

先日、React ベースのモバイル向け Web アプリに Auth0 の認証を実装したところ、Silent Authentication(サイレント認証)のタイミングでブラウザからトークンが消失し、ログイン状態が維持できない現象に遭遇しました。

調べたところ、Safari に搭載されているトラッキング防止機能の ITP(Intelligent Tracking Prevention / インテリジェント・トラッキング・プリベンション)が原因だと判明しました。

調べる過程で、Cookie の基本的な機能からアドテク周りの技術要素、最近のプライバシー保護トレンドについて触れる機会を得ましたので、技術ブログとして整理しました。

本記事では、以下の内容を扱います

  • Cookie(1st Party、3rd Party)
  • ITP(Intelligent Tracking Prevention)
  • ITP による、Auth0 の PKCE フローへの影響
    • 対応方法

前半は Cookie とプライバシー保護の話で、後半が Auth0 と ITP の話です。

Cookie とは

Cookie とは、Web サイトに訪れたユーザの情報を、一時的に保存する機能のことです。
この「一時保存する機能」により、ユーザのログイン状態を維持することや、Web ページに再訪したときに「この人は、以前にウチのサイトに来た〇〇さんだ!」と判定できます。

「以前に来た〇〇さん」と技術的に判定できると、次は「きっと〇〇さんならば…」という「Cookie により収集された個人属性の、Web 広告利用」へと直結させる動きが当然出てきます。

最近だとプライバシー保護の観点から、こういった Web 広告の規制が強化されるトレンドにあります。例えば、Web サイトのトップページに訪問した際に「Cookie の有効化に同意してください。Yes or No」がポップアップで表示されて、オプトインでの意思表示が求められるのは、このトレンドに乗ったものだと思います。

続いて、Cookie の分類を見ていきます。

Cookie の発行元が、訪問しているサイト(ドメイン)と同じか別かにより、1st Party Cookie と 3rd Party Cookie と呼び方が変わります。

Cookie の発行元と訪問しているサイト(ドメイン)の関係 Cookie の呼び方
同じ(Cookie の発行者は、訪問したサイトの運営者である) 1st Party Cookie
異なる(Cookie の発行者は、訪問しサイトとは別の外部の第三者である) 3rd Party Cookie

主に、外部のサービスを利用して「ユーザ行動に合わせた Web 広告を表示したい(ターゲティング広告を実施したい)」や「ログイン状態管理などの特定の機能を外部に任せたい」ケースで 3rd Party Cookie が利用されることが多いと思います。

ITP(Intelligent Tracking Prevention)とは

ひとこと言うと、ITP は「3rd Party Cookie の利用を禁止する技術」です。

先ほど、3rd Party Cookie により実現できることの 1 つに「ターゲティング広告(ユーザの行動履歴を元にした、Web 広告最適化)」があると述べました。ターゲティング広告により、各ユーザごとに個別最適化された(高いクリック率を獲得できる見込みの)Web 広告が表示できます。これにより、Web 広告のクリック率向上 → 購入率の向上が見込まれます。アドテク技術の進歩により、この Web 広告の精度が高まるほど、広告掲載ページ・広告を載せたい企業・その仕組みを提供する企業などの「Web マーケティング」界隈にとっては嬉しい世界になります。

その一方で、プライバシー保護の観点から、以下のような考え方が広まりつつあります。

(1)Web 広告の精度が高まる

(2) ユーザの趣味嗜好を高精度で特定できる

(3) 高精度な趣味嗜好の情報って、それはもはや個人情報では?

(4) 個人情報を無断でクロスドメインに共有するは、プライバシー保護観点から NG では?
(例えば、あるユーザ α の行動履歴を取得した A 社が、その情報を Web 広告機能を提供する B 社に「α の同意がない状況で」共有するケース)

このような考え方はメガテック企業でも意識され、Safari や Chrome などのブラウザによる規制も進んでいます。

例えば、Apple では 2017 年から Safari での 3rd Party Cookie の利用制限を段階的に導入しており、iOS14 ではついに Safari だけでなく Chrome・Firefox 含めて 3rd Party Cookie の利用が全面禁止になりました。
Google においても、Chrome での 3rd Party Cookie の利用を「2024 年後半に向けて段階的に廃止する可能性がある」と発表し、その代替技術として「プライバシー・サンドボックス」の開発・ユーザテストを進めています。ただ、Google は当初は 2022 年 1 月に規制を開始すると発表していましたが、その後に 2023 年後半に開始予定と延期し、さらに 2024 年後半と再延期しています。

Safari での ITP 規制状況を見ると、ユーザー情報のクロスサイトトラッキングを規制しようとする Apple と、規制の穴を探すアドテク企業の戦いが垣間見れます。

アップデート リリース 規制概要(*1)
ITP1.0 2017 年 9 月 特定の 3rd Party Cookie は 24 時間で削除
ITP2.0 2018 年 9 月 特定の 3rd Party Cookie は即時削除
ITP2.1 2019 年 3 月 特定の 1st Party Cookie は 7 日間で削除
ITP2.2 2019 年 4 月 特定の 1st Party Cookie は 24 時間で削除
ITP2.3 2019 年 9 月 特定の localstrage 上のデータを即時削除
iOS13.1 2020 年 3 月 全ての 3rd Party Cookie を即時削除
iOS14.0 2020 年 9 月 iOS で稼働する Firefox, Chrome にも ITP を適用開始

(*1)より詳細な規制内容はこちらを参照お願いします。

3rd Party Cookie は何もアドテク領域に閉じた技術ではなく、それ以外の分野でも利用されています。
次は、ITP により Auth0 のトークンがうまく動かなくなってしまう話に移ります。

Auth0 のトークン取得フローと ITP ブロックへの対応

Auth0 の React 用 SDK(auth0-react)を利用する場合、PKCE(Proof Key for Code Exchange)の認証認可フローに従います。フローの詳細はこちらのサイトに記載があります。

auth0_pkceフロー

Auth0 の JavaScript SDK ではログイン成功後、トークンを取得して、ブラウザのインメモリにキャッシュされます(上図での (9) で取得した Access Token をインメモリに保存する)。インメモリに保存すると、ページ遷移や画面リロードの度にトークンの再取得が必要で色々と面倒になりそうですが、この辺のトークンリフレッシュを Auth0 側では「Silent Authentication(サイレント認証)」により解決しています。サイレント認証により、ログイン状態を維持しながら、トークンをインメモリでセキュアに保持できます。

Auth0 x React でのログイン状態の管理が
(1)ID/Pass を入力してログインし、トークンを取得
(2)サイレント認証でトークンのリフレッシュ、ログイン状態を維持
(3)トークンの破棄、ログアウト
の 3 つで完結するならばこれで話は終わりですが、昨今の ITP(3rd Party Cookie の禁止)により、(2) のサイレント認証に失敗するケースが出てきました。

例えば、会社 Z が Auth0 でログイン機能を実装した Web サービスを運営しているとします。サービスの運営会社 Z と Auth0 では「異なるドメインの会社」になるため、Auth0 の発行したトークンが、Z 社の Web ページ上では 3rd Party Cookie と判定されて、ブラウザにより Cookie が強制消去されるケースが有り得る、ということです。サイレント認証に失敗すると「ログイン状態を維持できない(ページ遷移・リロードの度にログイン処理を求めることになる)」ため、ユーザ体験を大きく損なってしまいます。

ITP により 3rd Party Cookie が消去されたとき、Auth0 のコンソール画面、Safari の Web Inspector それぞれで以下の挙動が得られます。

auth0で失敗


Auth0 のコンソール画面では「ログインには成功」しているが「サイレント認証には失敗」している

サイレント認証に失敗


Web Inspector のネットワークのログから、前述した PKCE フロー (3) の /authorize は Call されているが、3rd Party Cookie がブラウザにより消去されているため、(7) の /oauth/token が Call されない。→ PKCE フローが途中終了しているため、認証は「失敗」である。

ITP への対応方法

サイレント認証が ITP により失敗する問題には、Auth0 公式が 2 つの対応方法を提示しています。

(1)リフレッシュトークンローテーションを設定する
(2)カスタムドメインを設定する

この 2 つを設定すれば、ITP による 3rd Party Cookie 消失問題には対応できます。

また、ブラウザの設定変更で「ITP をオフにする」ことも可能なので、問題切り分け手法の 1 つとして覚えておくと、後々に役立つかも知れません。

以下は iPhone のブラウザ設定画面です。
スクショは ITP がオンの状態で撮影したものなので、Safari は「『サイト越えトラッキングを防ぐ』をオフ」にすることで、Chrome は「『Web サイト超えトラッキングを許可』をオン」にすることで、ITP を無効化できます。

以下はリフレッシュトークン・カスタムドメインのどちらも設定せずに、エミュレーターの Safari 設定で ITP をオフにした場合の挙動です。Auth0 のコンソール画面、Web Inspector のログから、/authorize/oauth/tokenが Call されて、PKCE フローが正常終了してサイレント認証に成功していることが分かります。

おわりに

モバイル向けの Web ページを作成してリリースし、リリース後の動作チェックで「あれ、iOS だとログイン状態が維持できてない!?」と気づき、OAuth2.0 の仕様や PKCE の確認、インスペクタのログと認証フローと付き合わせながら、処理に失敗している場所の特定にまで至れました(1)「ITP」について知見がなかったこと、(2) 事前チェックが Android と Chrome シミュレーターだけで、iOS は工数削減のため未実施だったことが根原因なのですが、スマホと PC・iOS と Android で色々細かいところが違うのなー(なので、モバイル実機テストは Android と iOS は両方やろう)と再認識する機会になりました。

参照サイト