Sign in with Apple を本番でやらかしをしないために考えてみた
認証認可を趣味でやっている@nerocruxです。この記事は 認証認可技術 Advent Calendar 2019 第11日目の記事です。
本番でやらかした人のAdvent Calendar
ではありませんのでご注意ください。
...しかしこんなのやったら本番でもやらかしちゃうぞとの指摘があるかもしれませんので予めお詫びをしときます (´;ω;`)ウッ
そろそろ Sign In With Apple (以降、SIWA) を実装する時期がやってきました。本番で SIWA を実装したサービスも増えてきました。最近 pocket 以外に、vivinoも実装しており、さらにadobe creative cloudも実装しています(なぜかweb版のみだが)。
またAppleのCEOであるTime Cookさんもわざわざ日本に来てSIWAを実装したTimeTree社をtwitterで褒めたりしていて、SIWAを頑張って実装すればひょっとしたらTim氏が褒めに来るかもしれません。
Impressed with how @TimeTreeApp_jp helps millions of customers around the world manage their busy lives. Great to see you’re using Sign in with Apple—so important when you have sensitive information in your calendar like where your loved ones are. And that Dark Mode looks great! pic.twitter.com/PdV3nOgrjO
— Tim Cook (@tim_cook) December 9, 2019
仕事では自分が実装しているわけではないですが、趣味本位&相談されるときに困らない程度で仕様を調べたり、実装方法を考えたりしている程度で、せっかくなので今まで調べたことをまとめたいと思いましてこの記事を作成しました。
主に以下の観点から整理してみたいと思います。
あまり新しいネタないからつまらないかもしれませんが、しばらくお付き合いください。
各UAに対して、SIWA対応の必要性について個人的な考え
- 前提: Apple Store Review Guidelineに従いSIWA実装対象であること
iOS 13+
ガイドラインに従い、実装が必要です。ネイティブでサポートしているので、AuthenticationServicesに実装されている SIWA 関連のクラスを利用して実装するのが一般的だと考えます。
iOS 13 以外
AuthenticationServices 自体はiOS12からなんですが、SIWAに使われるクラスはiOS13からなので、SDKを利用した実装ができなくなります。
そのため、iOS13と同じように実装するのが不可能になるため、実装コストがかかります。
実装するかどうかの判断はビジネスに依存するんでどうすれば正しいかはケースバイケースで判断すると思いますが、一応自分の考え方をまとめます。
iOS 9、Android 6 未満
Sign in with Apple の仕様上、redirect_uri というパラメータをIDP(Apple)に登録する際、Custom URL Scheme (myapp://login/callback のようなスキーマ)を利用することが不可能となっており、必ず http(s):// から始まる必要がある。
そのため、iOS の UniversalLinks, Android の AppLinks の仕組みを利用することが必要となっている。
iOS 9, Android 6 未満のOSでは、このような仕組みをサポートしておらず、普通にやるなら Sign in with Apple の実装はできないはず。
iOS 9 ~ 12
iOS 13以下のバージョンに対して、必ずSIWAを実装しなければならないかをAppleのサポートに問い合わせたところ、「審査する前に特定のアイディアに対して予め承認することができません。アプリを提出したあとに適切なアドバイスをするよ」的な回答が返ってきました。なのでわからないです。
iOSそんなに詳しくないですが、色々聞いたり調べたりしたところ、ネイティブでこの機能サポートしてないので、古いバージョンのiOSを実装してなくても大丈夫なはず、との意見が多いです。
そうすると、個人的には以下の理由でiOS12以下にSIWAの実装を一旦しなくてもいいかなと思っています。
- 別のOSでSIWA経由でアカウント連携し、iOS12以下の端末でログインするニーズが少ないはず
- iOS13から入ったひとはiOS12にダウングレードする可能性が低い
- Androidの人でSIWA経由でユーザ登録、アカウント連携する人が少ない
- Web... どうだろう...
- 新規ユーザを獲得する際にSIWAというパスがなくてもそれほど影響がない
- iOS13未満の端末はどんどん減っていく
ただAndroidを対応する予定があれば、複雑な認可部分は同じフローで実装できそうなので、一緒に対応しちゃっていいかなと個人的に思います。
また、ユーザ数の多い大規模なサービスや社会的の影響の大きいサービスであれば、割合が少ないけど母数が大きいので、やはり捨てられないところがあると思います。
Android 6+
もともと Android のユーザだったら Sign in with Apple でユーザ登録することは多分ないと思うが、iOSから引っ越ししてくる人は数少なくないはず(Android で WebAuthn やりたい人とかね)です。また、iOS, Android両方利用する人も少なくありません。
なので、もしiOS, Android両方提供していれば、Androidは対応はやったほうがいいと思います。まぁそこもサービスの規模や性質、ユーザ数的の割合で判断すると思いますが。
Web
アプリと同等、あるいはそれ以上の機能をWebで提供していれば、SIWAも実装する必要があると思います。
特にパスワードのリセット、アカウントの停止など、アカウント/セキュリティまわりの機能をWebのみに実装しているサービスが多いと思いますので、そういったユーザに提供しなければならない機能がWebにあれば、ログインの手段を提供しなければなりません。
各UAに対して安全な実装方法について
訂正: @nov さんの指摘より、iOS 13/macOS catalina上で(最新の)safari経由でnonce付きの認可リクエストを送っても、帰ってくるID Token(frontchannel, backchannel 両方とも)にnonceが入らないことがわかりました。 また、iOS13の場合、safariだけでなく、chrome/firefox経由でも、AppleIDPに対する認可リクエストがネイティブにフックされ認証がネイティブのポップアップで行う場合、取得したID Tokenにnonceが入りません。macOSのchrome/firefoxの場合ID Tokenにnonceが入ります、古いバージョンのsafariは検証できてませんでした。 認証がiOS/macOSネイティブの認証機構にフックされた場合、ブラウザからIDPにリクエストが直接に届かれることなく、OSが認可リクエストを送り直している、その際nonceをちゃんとセットしてくれないって感じかな..? iOS12の場合、SIWAの実装がまだないので、ネイティブの認証画面が出ず、nonceもID Tokenに入ってました(frontchannel, backchannel 両方とも)。 なので、iOS13 + AuthenticationServices利用しない、または最新版のPC Safariに対する実装は、nonceの検証ができません。
Sign in with Appleとは、ID連携したいサービスが何かしらの方法で、Apple社が提供している(ほぼ)OpenID Connectに準する認可サーバと会話して、ユーザの認証と認可を行った上で、ユーザのID Tokenを入手する。いわゆる3-legged authorizationってやつです。
このID Tokenに、Appleで認証済みのユーザの(同じTeamID内で)一意なユーザIDが含まれており、Appleでのログインセッションをサービスのログインセッションに"引き継ぐ"ことで、サービスにログインする、というプロセスです。
iOS13では、Sign in with Appleに対して、ネイティブレベルでサポートしており、iOS開発者はネイティブのクラスを使って開発できる。
iOS13以外では、AppleがJSのSDKしか提供していない(しかも機能が単純、当たり前だが)ので、開発者はある程度OIDCのプロトコルを理解した上で、特にセキュリティ上の特性を把握した上で、実装しなければならないです。
なんだかわからんけどID Token取れた、そのsubからユーザIDも取れたから、subを後ろのサーバに送って終わり!と考えて実装したら、来年の本番の認証認可システムをやらかした人
のアドカレにデビューする可能性があるので、お気をつけください。
SIWAは Sign in with Google, Sign in with Lineなどと同じ、ソーシャルログインの一つなので、ネットに存在する"(OIDCを利用した)ソーシャルログインの安全な実装"に関連する記事がたくさんあるので、参考してみるといいです。
それでは、UAごとに自分が考えた実装例を紹介したいと思います。
※ シーケンス図にあるセッションについてに記述はあくまでも例です。
iOS13
iOSネイティブのAuthenticationServicesを利用して実装するのがベストでしょう。
認証はTouchID/FaceIDがサポートされ、認可はネイティブなUIによって行われ、ユーザからするとUX的にはよい。
開発者としてはAppleのドキュメントに従い実装すれば良いはず。特にOIDC的な要素がなくて、ASAppleIDCredentailが取得でき、以下の情報が取れるようになる(ASPasswordCredentialは割愛)
- identityToken(ID Token)
- authorizationCode
- fullName
- etc...
identityToken は JWT になっていて、パースすると以下のようなパラメータが取れる。
ASAuthorizationAppleIDRequestを作るときにnonceをセットすることができ、セットしていればレスポンスで受信するidentityTokenの中に含まれるので、検証可能となっています。
✻ Header { "kid": "AIDOPK1", "alg": "RS256" } ✻ Payload { "iss": "https://appleid.apple.com", "aud": "com.example.apple-samplecode.juice", "exp": 1575545337, "iat": 1575544737, "sub": "000738.b65425db0ef845379c5fbc5148c3516d.1047", "nonce": "jf329fui290-3uvj43290vjh3409hv", "c_hash": "eLyPhH3tcU22gPSF6zOxhQ", "email": "xxxxxxxxxxxx@privaterelay.appleid.com", "email_verified": "true", "is_private_email": "true", "auth_time": 1575544737 }
また、authorizationCodeを利用することで、上記identityTokenとほぼ同じようなID Tokenをバックチャンネルで取得できます。
後述、AuthenticationServicesを利用せずに実装するパターンを見るとわかりますが、SDKを使って実装する場合のレスポンスは大きな差異がなく、サーバサイトとしては同じように処理すればよいです。
注意してほしいのは、Appleが提供しているサンプルコードでは、nonceをASAuthorizationAppleIDRequestに渡しておらず、ガイドを読んだ感じでは"セッション引き継ぎ"の方法についても言及してなかったので、Apple UserID やメアドを使ってセッションを引き継ぎするのが危険なので、上記ID Tokenや認可コードをサーバに送ってセッションを引き継ぐほうが安全だと思います。 その際、nonceの生成・セット・検証を行うべきです。
iOS 9~12, Android 6+
AuthenticationServiceを利用せずに実装する場合、利用する場合と同じように、Front channel に id_token と auth_code、そしてBack ChannelにID Tokenを発行することができます。
ネイティブ用のSDKが提供されてないので、認可リクエストを組み立てて、Sign in with Appleのボタンをネイティブ画面上にセットしたり、Webviewを利用している場合JS SDKを利用することになると思います。
SIWAボタンがタップされた場合、ブラウザに遷移され、認証認可を行った上で、RedirectURIによってアプリに遷移し戻し、id_token や auth_code を入手する。ネイティブはこれらの情報をサーバに送り、サーバがログイン処理を行う。
こちらサーバ側の実装はiOS13の場合と同じと考えています。
リクエスト & レスポンス例
/authorize
リクエスト
https://appleid.apple.com/auth/authorize? client_id=com.nerocrux.siwa.service& scope=name%20email& response_type=code& // code id_token もOK redirect_uri=https%3A%2F%2Fsiwa.nerocrux.com%2Fcallback& prompt=login& response_mode=form_post& state=RpigrS5w9E97jtLUoUPgQ4RgZ6TuezU8 // なくてもAppleに怒られない nonce=k320fk3029jg50ijg6i5j409jf0o3jfk3409jh50 // なくてもAppleに怒られない
レスポンス
Host: https://siwa.nerocrux.com/callback state: RpigrS5w9E97jtLUoUPgQ4RgZ6TuezU8 code: c359c8401ed5540a6a47cd532ed38781d.0.nxty.UdOTBkNQu173S_vuxGmQ3Q id_token: eeyJraWQiOiJBSURPUEsxIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLm5lcm9jcnV4LnNpd2Euc2VydmljZSIsImV4cCI6MTU3NTM5MjU4NiwiaWF0IjoxNTc1MzkxOTg2LCJzdWIiOiIwMDA3MzguYjczYjI4MDBkZTBmNDhhMzkxNjVjZTI3YTUxYWM3YjAuMTYyMSIsIm5vbmNlIjoiazMyMGZrMzAyOWpnNTBpamc2aTVqNDA5amYwbzNqZmszNDA5amg1MCIsImNfaGFzaCI6Imt6eEFJVTVZcmt0ZFpYaHhpcFVvZVEiLCJhdXRoX3RpbWUiOjE1NzUzOTE5ODZ9.hbz0QX5PkwT1Gmq8I22M7mnOkU5cPY8ot9FCFP4wLBOmBYFcCeiVmojNNcrEfCZH4dxMptf1OTnNTsb56IPCQFByTHkiSULm9VJbMTt_oIvCSC8yfUPl7zKAPZtjJv3OxxJFS9kZ7bdjPYO-1iByKaqgJSG1OipmmjoC67zUgi4uMjCsWhLykqG2OWnWbTZ6PaVvM8QX-Ugl7WnhMNnTtJeeRAle8fgApiyYUXcHlaCDfX2i56HsuwXgPu1ARXlcJtjw2nYIDevzR2ekuLyAV9OKmuQymH4wY3xhMegp5low0ej-7CKRkN4x41AnRi2YDgyhaAEFiJoLopd_gxU8kg
ID Token
✻ Header { "kid": "AIDOPK1", "alg": "RS256" } ✻ Payload { "iss": "https://appleid.apple.com", "aud": "com.nerocrux.siwa.service", "exp": 1575392586, "iat": 1575391986, "sub": "000738.b73b2800de0f48a39165ce27a51ac7b0.1621", "nonce": "k320fk3029jg50ijg6i5j409jf0o3jfk3409jh50", "c_hash": "kzxAIU5YrktdZXhxipUoeQ", "auth_time": 1575391986 }
/token
リクエスト
POST /auth/token HTTP/1.1 Host: appleid.apple.com Content-Type: application/x-www-form-urlencoded client_id=com.nerocrux.siwa.service& client_secret=<CLIENT SECRET JWT>& code=c359c8401ed5540a6a47cd532ed38781d.0.nxty.UdOTBkNQu173S_vuxGmQ3Q& grant_type=authorization_code& redirect_uri=https%3A%2F%2Fsiwa.nerocrux.com%2Fcallback
レスポンス
{ "access_token": "a0e1055f108144071a8bb1bf915643c12.0.nxty.YAwyi9gPzMXB625gaqNYBg", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "<REFRESH_TOKEN>", "id_token": "eyJraWQiOiJBSURPUEsxIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLm5lcm9jcnV4LnNpd2Euc2VydmljZSIsImV4cCI6MTU3NTM5MjYxMSwiaWF0IjoxNTc1MzkyMDExLCJzdWIiOiIwMDA3MzguYjczYjI4MDBkZTBmNDhhMzkxNjVjZTI3YTUxYWM3YjAuMTYyMSIsIm5vbmNlIjoiazMyMGZrMzAyOWpnNTBpamc2aTVqNDA5amYwbzNqZmszNDA5amg1MCIsImF0X2hhc2giOiJmMmlkSGlSQ3RhclFqVkZSR3RyVVFRIiwiYXV0aF90aW1lIjoxNTc1MzkxOTg2fQ.kVNeCAxZVhPrXHwb4FzFzcs4OTVJ2LQOZUjFr2Ein0dnijfvM5qUV_srpnXPn2uJPIx_VkJ_Fyk144nyBpFbqAhDNt5qroqIQrHzgJYOt6QvOGCivPIa8Bj1qzXxUp3T56XCQgHTRaxL8Ym8hKXDbAX3JUDtwj9BKlZM__nNyliigGptDEsTa_97popZtYaNi8MOGi89pl3gmfC3JnzGuyUKcw-r1Z2lwdzwAkpL9RzsHsMzCsduGtM9cnu4WvsDG8UFHsXkaEzY8_pitvvVBVNdsinYanHdaNW1wrSFftJ_pfGSd603-Al2SFOAiedkgIyJaaSpjZnttYlfMqdkVg" }
ID Token
✻ Header { "kid": "AIDOPK1", "alg": "RS256" } ✻ Payload { "iss": "https://appleid.apple.com", "aud": "com.nerocrux.siwa.service", "exp": 1575392611, "iat": 1575392011, "sub": "000738.b73b2800de0f48a39165ce27a51ac7b0.1621", "nonce": "k320fk3029jg50ijg6i5j409jf0o3jfk3409jh50", "at_hash": "f2idHiRCtarQjVFRGtrUQQ", "auth_time": 1575391986 }
Web
Webの実装は、AuthenticationServiceを利用せずに実装するパターンとは同じです。異なる点としては、アプリを介さないため、サーバからnonceをアプリに送ったり、アプリからid_token, auth_codeをサーバに送ったりする必要がありません。
アップルはWeb向けに、JS SDKを提供しています。以下のようにかんたんに利用できます。
<html> <head> </head> <body> <script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script> <div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div> <script type="text/javascript"> AppleID.auth.init({ clientId : '[CLIENT_ID]', scope : '[SCOPES]', redirectURI: '[REDIRECT_URI]', state : '[STATE]', nonce : '[NONCE]' // nonce も設定できるぞ }); </script> </body> </html>
当然ながら、このライブラリの役割はOAuth2/OIDCが知らない人でもかんたんに認可URLを組み立てるように、必要なパラメータを入れるだけで、認可URLを組み立ててくれます。それ以上のことはできません。 JS SDKによって生成されたボタンをクリックすると、以下のURLに飛ばされます。
https://appleid.apple.com/auth/authorize? client_id=<CLIENT ID>& redirect_uri=<REDIRECT URI>& response_type=code%20id_token& state=<STATE>& scope=<SCOPE>& nonce=<NONCE>& response_mode=form_post& frame_id=fabb5677-bef5-4227-a828-527bb3cc9d64& m=12& v=1.4.1
なのでJS SDKを利用する場合、認可レスポンスに auth_code, id_token 両方返ってきます。
JS SDK使わなずに自前で認可URLを組み立てることも当然可能です。その場合、auth_codeのみ、id_tokenのみ取得するような設定もできます。
ただ、m
, v
などApple独自っぽいパラメータはどうすればいいか、つけなくていいかはわからない。
サーバでの実装
実装内容
セッションと nonce の生成部分
アプリを起動時にサーバと通信し、新しいセッションとランダムなnonce値を生成して、紐付きしてDBに保存する。
Session IDとnonceをアプリに返す
Auth Code / ID Token を受け取るためのエンドポイント
(1) アプリがこのAPIを利用して、Auth Code あるいは ID Token をバックエンドサーバに送信する。その後、サーバは以下の処理を行う。
backchannel ID Token を利用する場合 * frontchannel ID Token の有効性を検証した上で、c_hashを使ってAuth Codeの有効性を検証する(置き換えられているか) * Auth Codeを利用してトークンエンドポイントに叩いてAccessToken, RefreshToken, ID Tokenを取得する。 * 取得した ID Token を検証する * このID Tokenの中にat_hashが含まれているけど、access_token実際使いみちが今の所ないし、backchannelで発行されたので置き換えられる可能性が低いため、検証する必要があるかは悩ましいが、一応検証しとく
frontchannel ID Token を利用する場合
受信した ID Token の有効性を検証するだけ。
ID Token の検証について
検証はOIDCに定められている基準で行うとよいでしょう。
response_type = code id_token の場合、HybridFlowのFrontchannel ID Token検証方法とBackchannel ID Token検証方法をそれぞれご参照ください。
かんたんにリストアップすると、以下の項目が検証対象になります。
- signature : JWT自体は偽造されているか
- iss : 発行者は Apple か
- exp : 有効期限切れているか
- nonce : DBにある、当セッションと紐付いているnonceの値と一致するかどうか(ID Token置き換え攻撃対策)。また、無効化されているかどうか(リプレイ攻撃対策)。
- c_hash: auth_code と id_token は同じセッションで発行されたか(auth_codeの置き換え対策)
- at_hash: access_token と id_token は同じセッションで発行されたか(access_tokenの置き換え対策)
(2) ID Token をパースして、sub (AppleUserID) を当セッションと紐付ける。
- もしユーザがすでに登録していれば、該当するユーザをログインさせ、アプリに知らせる。
- もしユーザはまだ未登録であれば、ネイティブアプリに知らせ、ユーザ登録画面を表示し、新規登録を実行する。登録後、ユーザをログイン完了にする。
(3) nonce を無効化にする
Front Channel ID Token vs Back Channel ID Token
ご覧のように、ASAuthorizationAppleIDCredentialの中にID TokenとAuth Code両方入っています。このID Tokenをサーバに渡して使ってもらうか、それともAuth Codeをサーバ側渡して、サーバがAuth Codeをtokenエンドポイントに送って新たに取得したID Tokenを利用するかの二択があります。
ではどっちを利用するべきなのか。
自分は特に理由がなければ、バックエンドで取得したID Tokenを利用したいと考えています。理由は以下だと考えています。
- OAuth2のSecurity BCPはImplicit Grantを非推奨にしています。SIWAでresponse_type=code id_tokenのリクエストはHybridFlowなんだけどFrontchannelのID TokenはImplicitFlowで出るものに等しいので、トークン置換攻撃などに弱いので、利用するにはリスクが高くなりそう。
- BackchannelでAuth Code使ってID Tokenを取得する際、Auth Codeの置換攻撃を比較的に容易に防げる。また、クライアント認証が必須であるため、取得したID Tokenの正当性を担保する根拠が強い。
AuthenticationServicesを利用する場合、ID Token と Auth Code 両方帰ってくるので、ID Token を使うとしても、 c_hash を使って Auth Code を検証するためのみに利用する、くらいの用途しかない気がします。
また、AuthenticationServices利用しない場合、response_type = code にし、HybridFlowではなくAuthCodeFlowを利用してもいいかなと思っております。バックエンドでインターフェースを揃えたいなら、AuthenticationServicesと同じように、frontchannelのID TokenはあくまでもAuth Code検証用に使うようにしたい。
やむを得ない理由でfrontchannelのID Tokenを利用したい場合、ID Tokenが置き換えられていないことを担保するために、必ず認可リクエストにnonceをセットし、ID Tokenを受信したあとにnonceを検証する必要があると思います。
セキュアに実装するためのポイント
SIWAを利用してSSOを実装するとき、以下のようなリスクを注意すべきだと考えています。
- ネイティブの場合、サーバに送られた情報は偽造されたり、置換されたりするリスク
- セッションが攻撃者に奪われ、被害者に装わってログインする
- リプレイ攻撃
これらのリスクを軽減するために、サービスがSIWA実装時に、以下の措置を取るべきだと考えています。
- User Identity情報偽造/置換に対する防衛
- Apple User ID をサーバに送信するではなく、検証可能なID Tokenをサーバに送信する
- ID Token, Auth Code をOIDCの仕様に沿って検証する
- セッションの漏洩対策
- セッションIDを守る(範囲外のため割愛)
- リプレイ攻撃を防止するために
- nonceを検証する(存在、有効性)
- ログイン成功後にnonceを破棄する
終わりに
Sign in with Appleについて大したネタがなくて、愚痴しか言ってなかった気がしますが参考になれると嬉しいです。
アップルのガイドラインに従い、SIWAの実装がある場合、新しく作成するアプリではすでにSIWAを組み込む必要があって、既存のアプリでは2020年4月まで対応する必要がある言われています。実際ちゃんと実装しなければリジェクトされるかどうかまだわからないですが、天下のアップル様と仲良くしたいなら早めに実装しといたほうが無難でしょう。
明日はcorocnさんによるOAuth3のお話です。楽しみですね!
では良いお年を。
おまけ
またけさんがSIWAが出たまもなく頃のつぶやきですが
Sign in with Apple Demo で Apple の JS SDK の挙動も確認できるようにしてみた。form_post だから多分 Chrome の SameSite=Lax デフォな状態だと JS SDK だけログインコケると思う。 https://t.co/wDSa4hust6
— nov matake (@nov) 2019年6月7日
この問題、最近思い出して試してみたらまだ存在していました。
具体的にやったのは、Chrome Canaryで same site by default cookies を enabled し、Apple JSを使ったログインボタンをクリックするだけです。認証してアプリに対して許可すると認可レスポンスが400になります。
Apple JSを利用せず、自分でURLを組み立て、response_mode = form_pose ではなく、fragment, query にすると、一応認可レスポンスは成功しますが、Appleのポリシーにより、これらのresponse_modeではscopeの設定ができません。なので、ID Tokenは取れるが、ユーザ名(FullName)とEMAILは取れないです。
response_mode must be form_post when name or email scope is requested.
先日、Chrome は 80 から(2020年2月stableリリース) SameSite = LAX がデフォルトになると発表されました。Apple様はこの問題を直してくれないとちょっとやばいかもしれませんので、ちょいちょい様子をみてみたいです。