Rails 5, Apartment and Devise: subdomain login not working

Ive configured the Rails 5 app with Apartment (1.2.0) and Devise (4.2.0). Due to some DDNS issues, there is a limitation that the application is only available under app.myapp.com(note the subdomain app). myapp.comredirected to app.myapp.com.

My use case is that each user (tenant) who subscribes to the application must access his specific data through his subdomain (for example, tenant.myapp.com). Users should not be tied to their subdomain. In principle, you can log in from any subdomain. Redirection to the correct subdomain for the tenant is being processed ApplicationController. According to the development standard, the login page is at app.myapp.com/users/sign_in. This is where the problems begin:

The user cannot log in due to the error "email error or password."

In development I played a little. Logging in lvh.meworks fine. The user is logged in and redirected to his subdomain. Trying to do the same with app.lvh.meleads to the above problem.

Ive installed the session store as follows:

# /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)

Ive also tried a job that doesn't work either:

Rails.application.config.session_store :cookie_store, key: '_myapp_session', domain: :all

What do I need to do to log in from any subdomain?

Test case:

The user user1visits the url and app.myapp.com/users/sign_inprovides his credentials and therefore subscribes and redirects to user1.myapp.com.

Bonus: user1Visits the URL another_user.myapp.com/users/sign_inprovides its credentials and therefore subscribes and redirects to user1.myapp.com.

Edit

Other relevant configurations:

# /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

and

# /app/classes/excluded_subdomains.rb
class ExcludedSubdomains
  def self.subdomains
    %w( www admin test public private staging app web net )
  end # subdomains
end # class

and

# /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

and

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
+4
source share
2 answers

! .app , . :

# /config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: '_myapp_session', domain: {
  production:   '.myapp.com',
  staging:      '.myapp.com',
  development:  '.lvh.me'
}.fetch(Rails.env.to_sym, :all)

, . , , . GitHub.

+6

apartment, .

config.excluded_models = ["User"]

.

, . subdomain, tenant_name User / devise , .

session_store.rb session_store.rb, .testdomain.com .

Rails.application.config.session_store :cookie_store, key: '_jcrop_app_session', domain: ".testdomain.com"

, , myapp1 app, .

0

Source: https://habr.com/ru/post/1670863/


All Articles