Настройка обратного вызова SAML в Rails с помощью Devise и OmniAuth-SAML

EDIT: дополнительная информация и сжатый вопрос у основания;)

Я настраиваю интеграцию между небольшим приложением, которое я создаю, и поставщиком удостоверений, использующим SAML2.0.

В общем, я следую инструкциям на странице "Разработка", а затем в документах Omniauth-SAML.

В настоящее время проблема заключается в том, что путь обратного вызова не генерируется. Здесь соответствующие биты кода ниже; не стесняйтесь запрашивать дополнительную информацию.

приложение/модели/user.rb

class User < ActiveRecord::Base
  devise :omniauthable, omniauth_providers: [:saml]

  def from_omniauth(auth_hash)
    puts auth_hash
    new  # Stub for now I guess?
  end
end

приложение/контроллеры/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def saml
    @user = User.from_omniauth request.env['omniauth.auth']
    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication
      set_flash_message(:notice, :success, kind: 'SAML') if is_navicational_format?
    else
      session['devise.saml_data'] = request.env['omniauth.auth']
      redirect_to permission_denied # this isn't going to work lol
    end
  end

  def failure
    redirect_to root_path
  end
end

Усеченный и дезинфицированный фрагмент из config/initializers/devise.rb

  config.omniauth :saml,
                  idp_cert_fingerprint: 'aa:bb:cc...', # an actual fingerprint here 
                  idp_sso_target_url: 'https://sso.bla.thing.com/fss/idp/startSSO.ping?PartnerSpId=SAML_UID',
                  issuer: 'myidpname',  # Not actually sure what this should be
                  idp_entity_id: 'thingfssdp',
                  assertion_consumer_service_url: 'https://myapp.com/auth/saml/callback',
                  name_identifier_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'

В соответствии с документами здесь и здесь, добавив больше, чем указано выше (то есть, добавление дополнительных требований в config/initializers/omniauth.rb) было бы неверным.

Мои контроллеры имеют before_action :authenticate_user! в качестве первой строки.

config/routes.rb имеет следующую строку вверху:

Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

Но, возможно, важно отметить, что я еще не добавил вручную логику обработки обратного вызова

Попытка посетить мое приложение дает ERR_TOO_MANY_REDIRECTS; довольно много 302-х, все, очевидно, обращаясь к себе. Выполнение GET/auth/saml/callback приводит к следующей полезной ошибке (не уверен, как и почему/пользователи/получает там допинг, мне нужно запросить изменение в URL-адресе ACS или это то, что я контролирую?):

rails_error_message

Любое понимание или помощь будут высоко оценены.

EDIT: похоже, проблема заключается в том, что user_saml_omniauth_authorize_path устанавливается в /users/auth/saml, а не непосредственно на странице входа IDP. У меня нет явного контроллера для этого маршрута, но, по-видимому, требующий ввода для ДРУГИХ контроллеров означает, что мне нужно зарегистрироваться для этого. Конечным результатом является то, что, как некоторые предположили, мы получаем бесконечный цикл переадресации.

Ответ 1

О цикле переадресации: поскольку у вас есть before_action :authenticate_user!, он вызывает любой неавторизованный запрос для входа пользователей на страницу. Я предполагаю, что у вас также есть тот же обратный вызов на вашей странице входа. Таким образом, при каждом переадресации на /sign_in рельсы передают его через authenticate_user! и перенаправляют его снова, поскольку пользователь не аутентифицирован. Чтобы он работал правильно, вы должны skip_before_action :authenticate_user! в контроллере, где у вас есть знак (SessionController я предполагаю).

Что касается второго вопроса - правильный маршрут авторизации. ответ на приведенном скриншоте ниже ошибки. Вы можете видеть, что правильный путь /users/auth/saml и users/auth/saml/callback

UPDATE: пользователи по умолчанию добавляются в Devise (используя ваше имя модели)