Apartment (1.2.0) とDevise (4.2.0)で Rails 5 アプリケーションをセットアップしました。いくつかの DDNS の問題により、アプリにのみアクセスできるという制約がありますapp.myapp.com
(サブドメインに注意してくださいapp
)。myapp.com
にリダイレクトしapp.myapp.com
ます。
私の使用例は、アプリにサインアップしたすべてのユーザー (テナント) が、サブドメイン (例: tenant.myapp.com
) を介して特定のデータにアクセスする必要があるというものです。ユーザーのスコープをサブドメインに限定しないでください。基本的にどのサブドメインからでもサインインできるはずです。テナントの正しいサブドメインへのリダイレクトは、によって処理されApplicationController
ます。Devise の標準に従って、ログイン ページは にありますapp.myapp.com/users/sign_in
。ここから問題が始まります。
「メールアドレスまたはパスワードが正しくありません」エラーのため、ユーザーはログインできません。
開発中、ちょっと遊んでみました。からのサインインはlvh.me
完全にうまく機能します。ユーザーがログインし、サブドメインにリダイレクトされます。で同じことをapp.lvh.me
試みると、前述の問題が発生します。
セッション ストアを次のように設定しました。
# /config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: '_myapp_session', domain: {
production: '.app.myapp.com',
staging: '.app.myapp.com',
development: '.app.lvh.me'
}.fetch(Rails.env.to_sym, :all)
また、次のことも試しましたが、どちらも機能しません。
Rails.application.config.session_store :cookie_store, key: '_myapp_session', domain: :all
どのサブドメインからでもログインできるようにするには、どうすればよいですか?
テスト ケースは次のようになります。
ユーザーは資格情報を提供user1
する URL にアクセスapp.myapp.com/users/sign_in
し、そのためサインインして にリダイレクトされuser1.myapp.com
ます。
おまけ: user1
URL にアクセスanother_user.myapp.com/users/sign_in
すると資格情報が提供されるため、サインインして にリダイレクトされuser1.myapp.com
ます。
編集
その他の関連する構成:
# /config/initializers/apartment.rb
config.excluded_models = %w{ User }
config.tenant_names = lambda { User.pluck :subdomain }
config.tld_length = 2
Rails.application.config.middleware.insert_before Warden::Manager, Apartment::Elevators::FirstSubdomain
Apartment::Elevators::FirstSubdomain.excluded_subdomains = ExcludedSubdomains.subdomains
と
# /app/classes/excluded_subdomains.rb
class ExcludedSubdomains
def self.subdomains
%w( www admin test public private staging app web net )
end # subdomains
end # class
と
# /app/models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable
after_create :create_tenant
after_destroy :delete_tenant
# other stuff
def create_tenant
Apartment::Tenant.create(subdomain)
end # create_tenant
def delete_tenant
Apartment::Tenant.drop(subdomain)
end # delete_tenant
end # class
と
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
before_action :redirect_to_subdomain
private
def redirect_to_subdomain
return if self.is_a?(DeviseController) || self.is_a?(Users::OnboardingController)
if current_user.present? && request.subdomain != current_user.subdomain
redirect_to main_index_url(subdomain: current_user.subdomain)
end # if
end # redirect_to_subdomain
def after_sign_in_path_for(resource_or_scope)
users_onboarding_start_url(subdomain: resource_or_scope.subdomain)
end # after_sign_in_path_for
def after_sign_out_path_for(resource_or_scope)
successful_logout_url(subdomain: '')
end # after_sign_out_path_for
end # class