Skip to content

Remote logout

Alexander Keramidas edited this page Feb 17, 2017 · 5 revisions

So far, your users are able to log in to your Rails application by using the Authentiq ID application on their mobile phone. So after logging in and finishing their work, naturally they would want to log out of your application, so that they can be and feel secure. This can be done via the log out link in your Rails application or via the Authentiq ID mobile app.

Continue reading below to find out how to do this.

Remote Logout (Backchannel-logout)

Authentiq Omniauth strategy provides the ability to log out remotely via the Authentiq ID app by providing a proc/lambda for the remote_sign_out_handler option.

To test the remote logout functionality in Rails under a development environment you need to enable rails caching for development environment

Example with Devise and Omniauth-Authentiq

Add Authentiq configuration and the relevant proc/lambda (to check and delete the Authentiq session when a logout request arrives) in the config/initializers/devise.rb file

config.omniauth :authentiq, ENV["AUTHENTIQ_APP_ID"], ENV["AUTHENTIQ_APP_SECRET"], 
                {
                scope: 'aq:name email~rs address phone aq:push',
                remote_sign_out_handler: (
                    lambda do |request|
                      if Rails.cache.read("application_name:#{:authentiq}:#{request.params['sid']}").present?
                        Rails.cache.delete("application_name:#{:authentiq}:#{request.params['sid']}")
                        true
                      else
                        false
                      end
                    end
                  )
                }

Add a check to save the session in the authentiq function that should exist in the app/controllers/users/omniauth_callbacks_controller.rb file as suggested by Devise when using it in conjunction with omniauth (single or multiple providers)

    if params['sid']
      Rails.cache.write("application_name:#{:authentiq}:#{params['sid']}", params['sid'], expires_in: 28800)
      session[:authentiq_sessions] ||= {}
      session[:authentiq_sessions][:authentiq] = params['sid']
    end

Add an action to validate the Authentiq session on the app/controllers/application_controller.rb file

  before_action :validate_authentiq_session!
  protect_from_forgery with: :exception

  def validate_authentiq_session!
    return unless signed_in? && session[:authentiq_sessions]

    valid = session[:authentiq_sessions].all? do |provider, session|
      Rails.cache.read("application_name:#{provider}:#{session}").present?
    end

    unless valid
      session[:authentiq_sessions] = nil
      sign_out current_user
      redirect_to new_user_session_path
    end
  end

Example only with Omniauth-Authentiq

Add Authentiq configuration and the relevant proc/lambda (to check and delete the Authentiq session when a logout request arrives) in the config/initializers/omniauth.rb file.

  provider :authentiq, ENV["AUTHENTIQ_APP_ID"], ENV["AUTHENTIQ_APP_SECRET"],
           {
              scope: 'aq:name email~rs aq:push phone address',
              remote_sign_out_handler: (
                lambda do |request|
                  if Rails.cache.read("application_name:#{:authentiq}:#{request.params['sid']}").present?
                    Rails.cache.delete("application_name:#{:authentiq}:#{request.params['sid']}")
                    true
                  else
                    false
                  end
                end
              )
           }

Add a check to save the session in the function that creates the session in the app/controllers/sessions_controller.rb file

    if params['sid']
      Rails.cache.write("application_name:#{:authentiq}:#{params['sid']}", params['sid'], expires_in: 28800)
      session[:authentiq_sessions] ||= {}
      session[:authentiq_sessions][:authentiq] = params['sid']
    end

Add an action to validate the Authentiq session on the app/controllers/application_controller.rb file

  before_action :validate_authentiq_session!
  protect_from_forgery with: :exception

  def validate_authentiq_session!
    return unless current_user && session[:authentiq_sessions]

    valid = session[:authentiq_sessions].all? do |provider, ticket|
      Rails.cache.read("omnivise:#{provider}:#{ticket}").present?
    end

    unless valid
      session[:authentiq_sessions] = nil
      reset_session
      redirect_to root_path
    end
  end