Appleでサインイン

@David、PR の著者が私のコメントに返信しました。これについてあなたの意見はどうですか?

私:

この PR は、名前とメールアドレスが不足している問題を解決しているように見えますか?

PR 著者:

いいえ、残念ながら違います。Apple は REST API エンドポイントを提供して名前やメールアドレスを取得する必要があります。現在、この情報は初回の認証成功時にのみ渡され、その後の認証時には渡されないためです。

初期認証時のワンタイム取得だけで十分ではありませんか?

何もしないよりはマシですが、それでも十分ではありません。例えば、「Appleでサインイン」を選択した後、「アカウント作成」画面でキャンセルをクリックした場合や、既存のアカウントをAppleと連携させた後、代わりに新しいアカウントを作成すると決めた場合などが考えられます。ベータ版終了までにAppleがこの問題を解決してくれることを願っています🙏

「いいね!」 5

現在、Apple でサインイン機能の実装は可能でしょうか?私が携わっているマーケットプレイス系のサイトでは iOS アプリの展開を予定していますが、このオプションがない場合、アプリ審査ガイドライン違反で却下されるリスクを避けるために、他の認証オプションを有効化できません。

私の知る限りでは、そのようなことはありません。この問題の解決を待っている状況ですが、リポジトリの所有者が不親切にもクローズしてしまいました。How to retrieve email and name? · Issue #8 · nhosoya/omniauth-apple · GitHub

あまり自信はありませんが、このコミット8 月の他のコミット は問題を解決しませんか?

プラグインをインストールしてテストしていただいて構いませんが、まだ解決されているとは聞いていません。ただし、開発者が十分な時間を取って確認するまで、あるいは少なくとも完了するまでは、本番環境での使用はお勧めしません。

この機能には大いに賛成です。他のサインインオプションと同様に、ヴァニラの Discourse に組み込まれることを願っています。

おそらく、そのような情報を意図的に取得できないのだと思います。

あなたのアプリや Web サイトに「Apple でサインイン」ボタンを表示することは、すでに持っている Apple ID を使ってワンタップでサインインまたはサインアップでき、フォームの入力、メールアドレスの検証、パスワードの選択を省略できることを意味します。「Apple でサインイン」は、アプリや Web サイトへのシンプルで迅速なサインインを可能にする新しい、よりプライバシーに配慮した方法を提供し、人々が信頼できる一貫したサインイン体験と、複数のアカウントやパスワードを記憶する必要がない利便性を提供します。名前とメールアドレスの入力を求める場合でも、ユーザーはメールアドレスを非公開にし、代わりに一意のランダムなメールアドレスを共有するオプションを持っています。

Apple の公式開発者記事を参照

おっしゃる通り、プライバシーは「Appleでサインイン」の重要な要素の一つです。しかし、ご引用の核心部分は以下の通りです。

ユーザーが名前やメールアドレスの提供を選択した場合、ログインのたびにプロバイダーからそれらを受け取ることが期待されます。現在の実装では、このようにはなっていません。最初の認証後、ユーザー情報が取得されません。

これはgemの作成者が修正できる問題ではなく、Apple側で変更が必要なものだと考えられます。それが近々実現するとは考えにくいので、ユーザーにDiscourse上で手動で名前やメールアドレスを入力してもらうしかないかもしれません😢

「いいね!」 4

はい、では情報を提供しないことを選んだ人たちはどうなるのでしょうか?

それと、ちょっと荒っぽいコンセプト案です :sweat_smile:

良い知らせです:

Robert/merefield 氏のプラグインのフォークを部分的に動作させることができました(このフォークは、GitHub 上の最新ソースからビルドした omniauth gem のコピーに切り替えるだけのものです)。ただし、HTTPS エンドツーエンドで ngrok を経由している私のテスト Discourse では、認証を動作させるために「サイト設定」の「同じサイトクッキー」を(なし)に設定する必要がありました。この設定を無効化すると、サインアップフォームを閉じた後でもアカウントを作成でき、再度ログインすることもできますが、設定を有効化するとログインできなくなります。

失敗したログイン試行のバックトレースを以下に示します:

失敗したログインのバックトレース
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.5.1/lib/logster/logger.rb:112:in `report_to_store'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.5.1/lib/logster/logger.rb:103:in `add_with_opts'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.5.1/lib/logster/logger.rb:54:in `add'
/usr/local/lib/ruby/2.6.0/logger.rb:543:in `error'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:163:in `log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:486:in `fail!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-oauth2-1.6.0/lib/omniauth/strategies/oauth2.rb:71:in `callback_phase'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:238:in `callback_call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:189:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/builder.rb:64:in `call'
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:47:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/tempfile_reaper.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/conditional_get.rb:38:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/head.rb:12:in `call'
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
/var/www/discourse/lib/middleware/anonymous_cache.rb:318:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/session/abstract/id.rb:259:in `context'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/session/abstract/id.rb:253:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/cookies.rb:648:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:101:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/debug_exceptions.rb:32:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.5.1/lib/logster/middleware/reporter.rb:43:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.1/lib/rails/rack/logger.rb:38:in `call_app'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.1/lib/rails/rack/logger.rb:28:in `call'
/var/www/discourse/config/initializers/100-quiet_logger.rb:18:in `call'
/var/www/discourse/config/initializers/100-silence_logger.rb:31:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/request_id.rb:27:in `call'
/var/www/discourse/lib/middleware/enforce_hostname.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/method_override.rb:22:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/executor.rb:14:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/sendfile.rb:111:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.1/lib/action_dispatch/middleware/host_authorization.rb:77:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.1.4/lib/mini_profiler/profiler.rb:184:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/message_bus-2.2.3/lib/message_bus/rack/middleware.rb:57:in `call'
/var/www/discourse/lib/middleware/request_tracker.rb:181:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.1/lib/rails/engine.rb:526:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.1/lib/rails/railtie.rb:190:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-6.0.1/lib/rails/railtie.rb:190:in `method_missing'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/urlmap.rb:68:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/urlmap.rb:53:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.8/lib/rack/urlmap.rb:53:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.2/lib/unicorn/http_server.rb:605:in `process_client'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.2/lib/unicorn/http_server.rb:700:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.2/lib/unicorn/http_server.rb:548:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.2/lib/unicorn/http_server.rb:144:in `start'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.2/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `<main>'

このプラグインのコア機能を動作させるために、このサイト設定を無効化しなくてもよくなるように、プラグインをどのように書き換えられるか、あるいは書き換えられるかどうかについて、何かご提案はありますか?私のプラグインコードは https://github.com/sau226dev/discourse-sign-in-with-apple にあり、omniauth gem の再ビルドに使用した最新コードも同じ GitHub オーガニゼーションにあります。

ご協力いただける場合は、事前にありがとうございます。

sau226

「いいね!」 4

このプラグインは当初、ある程度機能していましたが、上記のDavidが指摘した問題のため、最近はその対応がなされていません。

Appleが根本的なブロック要因(ログイン試行ごとに名前とメールアドレスを送信する仕組み)を解消したという好ましいニュースが届くまで、このコードを維持する価値はないと思います。これを回避する方法はないのでしょうか?そのため、依存関係の更新を試みてさえいませんでした。いずれにせよ、プラグインのテストは失敗するでしょう。

したがって、これは「リリース済み」のプラグインではありません(そうでなければ、この話題や類似のトピックは#pluginチャンネルに存在するはずです)。また、上記の状況が解決するまで、サポートは提供されない可能性が高いです。もしその問題が解決し、Appleがその情報を提供してくれたら、喜んで仕上げの作業まで行うつもりです。

ちなみに、もう一つ重大な問題があります。自分のサイトでこれを使用するには、AppleのシステムでのセットアップにアクセスするためにApple Developerプログラムへの有料登録が必要です。これは無料または低価格での登録ではないため、予算が限られている多くのサイトを遠ざけてしまうのではないかと懸念されます。

「いいね!」 6

@sau226 氏は、返却されたメールや名前がないことが、実際にはブロック要因ではないと示唆しているように思われます。

@orenwolf 後続のログイン時にメールや名前が返されないという事象は、問題には見当たりませんでした。サインアップウィンドウを閉じて、正しい情報を渡してサインアップを再開できたと思います。前述の通り、その後は Apple で問題なく直接ログインできました。

私が直面した唯一の問題は、前述のサイト設定を無効にしない限り発生する CSRF エラーです。もう一つの潜在的な問題は、サインインフォームに名前欄がないこと、およびユーザー名がメールアドレスの @ 記号より前の部分になることです(ただし私の見解では、これらは問題ではないか、ユーザー側で簡単に修正できる事項です)。

「いいね!」 4

上記の David のコメントに加え、Apple の開発者サポートサイトで関連トピックを見つけました。そこには公式の回答があり、この問題が確認されています。

公式回答:

こんにちは aslkdjalksdjasdasd さん、
これは正常に動作しています。ユーザー情報は、ASAuthorizationAppleIDCredential において、ユーザーが初めてサインアップした際のみ送信されます。同じアカウントを使って後から「Apple でサインイン」でアプリにログインする場合は、ユーザー情報は共有されず、ASAuthorizationAppleIDCredential にはユーザー識別子のみが返されます。アカウントがサーバー上で正常に作成されたことを確認できるまで、ユーザー情報が含まれる最初の ASAuthorizationAppleIDCredential を安全にキャッシュしておくことをお勧めします。
Patrick

ある開発者は以下のようにコメントしています。

待ってよ…もし何らかの理由で Apple からの最初のリダイレクトが、非常に一般的な理由のいずれかによって失われた場合、そのユーザーの情報を取得する他の手段がないため、そのユーザーは永久に失われてしまいます。この情報を取得する他の方法はないのでしょうか?

別の開発者はこう述べています。

または、下流で何か問題が発生した場合、顧客からクレームが来て、サポート担当者が Apple ID ウェブサイトへアクセスして権限を取り消すよう指示し、再度正しく登録できるようにするでしょう。これはひどい体験となり、このような問題が発生し始めると、人々がこのログインメカニズムを使わなくなると思います。

したがって、残念ながらこの機能を本番環境で安全に使用することはできないと思います。これはサポート面で地獄の状況(ナイトメア)となるでしょう。

Apple が作り出した問題に気がつくまで、これを棚上げにすることを提案します。セキュリティを向上させようとした結果、頑健性が過度に犠牲になっているように思われます。

「いいね!」 11

残念ですね。:cry:

「いいね!」 1

Appleは、「Appleでサインイン」のデベロッパーページを更新し、データ収集やデータ管理などに関する情報を追加しました。

「いいね!」 5

pull request を開き、omniauth-apple gem を最新バージョンに更新しました。これには このコミット が含まれており、ログイン時にユーザーのメールアドレスが毎回受け取れないという問題が解決する可能性があります。

これを試すために、認証情報を設定するために 推奨されているブログ記事 に従いましたが、まだ以下の 2 つの点で理解できていません。

  • Apple でサービス ID を設定するために必要なリダイレクト用リターン URL のパスは何か?
  • 「検証用 txt」はどうすれば取得できるか、あるいはそれは不要か?調べてみると、これは Apple からドメイン/メール通信設定の一部としてダウンロードできるとの記載がありましたが、現在はそうではないようです。
「いいね!」 3

ありがとうございます。

通常は、何かを正常にテストした後に PR を提出します :wink:

完了しましたら、ご確認ください。

これは明らかに解決策のように思えますが、Apple が「毎回メールを送信するようになった」という公式見解を出してくれれば、より安心できるでしょう。Apple が根本的な問題に対処していない限り、gem のバージョンを変更しても解決しません。

Apple Developer への再登録(まだ行っていません)をする際に、私の設定を確認してみます……(正直なところ、この騒動は少しやる気を削がれました)

@David

プラグインのフォークを アップデート し、最新の omniauth-apple を使用しようと試みました(バージョン番号の更新だけでなく、他にもいくつかの変更が必要である点にご注意ください)。

tl;dr: まだ動作しません

サンドボックス環境では一時的に動作するようにハックしましたが、依然としていくつかの問題が残っています:

  1. Apple はコールバックで POST リクエストを使用しています。これは OAuth 実装では一般的ではなく、samesite=Lax のクッキーがリクエストと一緒に送信されないことを意味します。その結果、Discourse はコールバック中にセッションクッキーを読み取ることができず、CSRF エラーをスローしてしまいます。

    非安全な回避策として、Discourse のクッキーを samesite=None に変更してこのセキュリティ機能を無効化する方法があります。

  2. CSRF トークンなしで POST リクエストを使用すると、コア部分の別のセキュリティ対策もトリガーされてしまいます。

    非安全な回避策として、この行 を削除する方法があります。

  3. omniauth gem が JWKs を取得 する際、Apple から 403 エラーが返されていました。Accept: ヘッダーが正しく設定されていないのではないかと疑っていますが、まだ確認できていません。

    非安全な回避策として、キーをハードコーディングする方法がありました。

これらの作業の末、ようやく Apple でのログインに成功しました。https://sandbox.dtaylor.uk で試すことができます(数日間動作させたままにしますが、ここには非安全なため、機密性の高い情報は入力しないでください)。

しかしその後、メールや名前は最初の認証時のみ含まれるという問題が残っています。試してみてください:Apple でサインインし、アカウント作成をキャンセルしてから再度試みます。2 回目の試みでは、あなたの情報が欠落しています。

つまり、Apple が近々仕様を変更しない限り、これをどう実現すればよいでしょうか?

(1) と (2) については、セキュリティを損なうことなく、Apple の POST を GET に変換できると思います。コールバックで POST を受け取った際、window.location='/auth/apple/callback?code=...&state=...' を設定する JavaScript をレンダリングします。そこから先は、他のプロバイダーと同じように動作するはずです。ただし、POST をインターセプトするには、コア API の変更が必要になると思われます。

(3) については、omniauth gem で少し手を加えることで修正できるかもしれません。

しかし、依然として名前やメールが取得できない状況に置かれているため、これらの他の問題を修正する価値があるかどうかはわかりません :cry:

「いいね!」 8

再挑戦してくださり、分析もありがとうございます!残りの問題について光明が得られるよう、Appleにテクニカルサポートインシデントを提出してみてはいかがでしょうか?私の経験では、Appleのデベロッパーフォーラムよりも、こちらでより多くの可能性のある解決策や回避策が提供される傾向があります。