Реализация входа через Apple в Discourse с использованием API

Привет! Я работаю над созданием API для входа в Discourse через Apple. Я уже установил плагин и следовал инструкциям из Discourse Apple Authentication. Всё работает корректно при входе в Discourse с Apple-аккаунтом через веб-сайт.

Изучив процесс входа через Apple с веб-интерфейса, я заметил, что происходит перенаправление на страницу Apple для авторизации, после успешного входа генерируется код от Apple, и затем происходит перенаправление на:

POST {{discourse_host}}/auth/apple/callback с параметрами state:{state}, code:{код от Apple}

После этого следует перенаправление на GET {{discourse_host}}/auth/apple/callback?code={{код от Apple}}&state={state}, в результате чего устанавливается новый cookie, который будет использоваться в API Discourse.

Исходя из этого процесса, я ожидаю, что после вызова /auth/apple/callback будет сгенерирован новый cookie.

Однако при попытке вызвать API я получаю ошибку: Authorization timed out, or you have switched browsers. Please try again.

Я попробовал снова с новым кодом, сгенерированным Apple, но получил ту же ошибку.

При проверке логов я вижу следующее:

Started GET "/auth/apple/callback?code=c32f105b5084d42b8bd3e7051873ddb55.0.rrzxz.pChPU9zGlXIHHhgEXLiA5g&state=fbi3bbboud" for
(apple) Setup endpoint detected, running now.
(apple) Callback phase initiated.
(apple) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
Started GET "/auth/failure?message=csrf_detected&strategy=apple" for 123.253.233.16 at 2023-11-27 06:10:28 +0000
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"message"=>"csrf_detected", "strategy"=>"apple"}
  Rendered users/omniauth_callbacks/failure.html.erb within layouts/no_ember (Duration: 4.1ms | Allocations: 17)
  Rendered layout layouts/no_ember.html.erb (Duration: 57.5ms | Allocations: 2882)

Message (47 copies reported)

(apple) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

Backtrace

/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:163:in `log'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:486:in `fail!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-oauth2-1.7.3/lib/omniauth/strategies/oauth2.rb:87:in `callback_phase'
/var/www/discourse/plugins/discourse-apple-auth/lib/omniauth_apple.rb:60:in `callback_phase'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:238:in `callback_call'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:189:in `call!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:192:in `call!'

Поэтому хочу спросить: верно ли я выбрал направление для использования входа через Apple в Discourse с помощью API и как решить проблему с ошибкой csrf_detected?

Аутентификация через Apple (как и все остальные методы аутентификации в Discourse) не предназначена для использования через API. Она должна использоваться конечными пользователями напрямую в поддерживаемом браузере.

Какую проблему вы пытаетесь решить? Возможно, мы сможем найти альтернативное решение.

Привет, @david, спасибо за ответ. То, что я хочу здесь реализовать, — это создать API для входа через Apple, которое будет использоваться мобильным приложением для доступа к API Discourse.

Для входа в Discourse с использованием электронной почты и пароля всё работает корректно с помощью этих двух API:

  1. {{discourse_host}}/session/csrf.json: этот API возвращает cookie и CSRF-токен, которые будут использованы для входа с помощью следующего API.
  2. {{discourse_host}}/session: этот API возвращает новый cookie, который можно использовать для доступа к другим API Discourse.
API CSRF

Сессия

Я ожидаю, что это будет аналогично входу через Apple в Discourse, где я делаю запрос к API Discourse для генерации cookie _t.

Привет @david, у тебя есть решение моей проблемы?

Боюсь, что простого ответа нет. API аутентификации, подобные этому, специально разработаны для того, чтобы предотвратить их срабатывание без реального взаимодействия пользователя в веб-среде.

Для вашего случая более распространенным решением было бы использование системы ключей API пользователя. Это позволит Discourse обрабатывать 100% логики аутентификации и предоставит вашему приложению ключи API для каждого пользователя. Такая стратегия должна быть гораздо более надежной, чем попытка «подделать» сессию пользователя.