Единый выход из нескольких приложений от провайдера Doorkeeper

Я использую Doorkeeper для своего приложения Rails и пытаюсь сделать так, чтобы, когда пользователь выходит из провайдера Doorkeeper, пользователь автоматически выходил из всех приложений.

По умолчанию, когда пользователь выходит из приложения, он по-прежнему будет входить в приложение поставщика привратника.

Это мой контроллер сеансов от моего провайдера Doorkeeper.

class SessionsController < ApplicationController
  def new
    redirect_to root_path if current_user
    session[:return_to] = params[:return_to] if params[:return_to]
  end

  def create
    user = User.find_by_email(params[:email])
    if user && user.authenticate(params[:password])
      session[:user_id] = user.id
      if session[:return_to]
        redirect_to session[:return_to]
        session[:return_to] = nil
      else
        redirect_to root_path

      end
    else
      flash.now.alert = "Email or password is invalid"
      render "new"
    end
  end

  def destroy
    session[:user_id] = nil
    flash[:alert] = "Sign Out successfully"
    redirect_to new_session_path
  end
end

Это мой контроллер сеанса из одного из моих приложений:

    class SessionsController < ApplicationController
  def create
    auth = request.env["omniauth.auth"]
    user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth)
    session[:user_id] = user.id
    session[:access_token] = auth["credentials"]["token"]
    redirect_to root_url
  end

  def destroy
    session[:user_id] = nil
    session[:access_token] = nil
    redirect_to root_url
  end
end

Я написал свою собственную аутентификацию пользователя для приложения провайдера Doorkeeper, но я использовал Devise для собственного приложения, подключенного к моему приложению провайдера Doorkepeer.

На данный момент, когда я выхожу из своего приложения Doorkeeper, я все еще вхожу в другое приложение. Итак, как мне сделать так, чтобы я выходил из сторожа, и это также заставит меня выйти из всех приложений?


person Amirol Ahmad    schedule 30.07.2015    source источник
comment
Приложения совместно используют БД?   -  person bbozo    schedule 04.08.2015
comment
@bbozo нет, приложения не используют базы данных совместно. у меня есть отдельная таблица пользователей в моем клиентском приложении.   -  person Amirol Ahmad    schedule 05.08.2015
comment
Хм, может быть, я ошибаюсь, но, насколько я понимаю, привратник просто аутентифицирует пользователя изначально, отдельные хранилища сеансов приложений обрабатывают вещи оттуда и не пингуют провайдера oauth при каждом запросе, возможно, если вы использовали общее хранилище сеансов для Все приложения? Должно быть достаточно переопределить session, чтобы вернуть user_id и access_token из кэша памяти или сервера Redis, который используется всеми приложениями?   -  person bbozo    schedule 05.08.2015
comment
Если вы можете подтвердить, что это действительно так, я напишу вам пример кода, как это сделать :)   -  person bbozo    schedule 05.08.2015
comment
@bbozo да, вот как это работает. Было бы здорово, если бы вы могли предоставить пример кода, как это сделать   -  person Amirol Ahmad    schedule 10.08.2015


Ответы (3)


вам нужно будет либо отправить вызов API из приложения привратника в каждое клиентское приложение, сообщая им об удалении сеансов для определенного пользователя, либо вам нужно, чтобы ваше клиентское приложение регулярно запрашивало приложение привратника, чтобы убедиться, что сеанс или токен доступа все еще активный. Последнее, вероятно, является лучшей стратегией, хотя в конечном итоге это приведет к большему количеству вызовов API.

person Eugene G    schedule 01.08.2015
comment
Быстрое обновление: с тех пор я реализовал такое решение. Приложение привратника будет принимать запросы на /session/destroy вместе с токеном доступа. Затем он уничтожит любой существующий сеанс для этого токена. Каждое приложение отправляет такое сообщение при выходе. - person Eugene G; 09.10.2015


Как я это вижу, вы можете синхронизировать состояния между приложениями либо с помощью относительно сложного обмена вызовами API (склонен к сетевым ошибкам, «одно из моих приложений просто перезапускался» и т. д.), либо с помощью общего хранилища. , лучшими вариантами, вероятно, являются общий memcached или общий сервер Redis, на котором будут храниться токены доступа для ваших идентификаторов пользователей.

Один из способов решить эту проблему — переопределить session в ApplicationController всех ваших клиентских приложений привратника и заставить их пинговать общее хранилище, когда что-то хочет получить или установить :access_token.

Обратите внимание, что я не сторонник переопределения хэшей [] и []=, потому что это нарушает принцип наименьшего удивления, но я считаю, что это лучший подход в данном случае.

Я даю вам пример кода для переопределения экземпляра session, чтобы сделать именно это: https://gist.github.com/bbozo/f5c28fe9bd804dff0af8 с помощью клиента memcached Dalli. Обратите внимание:

  • Подход Redis такой же простой (https://github.com/redis/redis-rb) ,
  • есть много вариантов «бесплатно начать» для обоих, вот любимый героку для memcachier: https://www.memcachier.com/pricing (как вы можете заметить, МНОГО 80-байтовых токенов аутентификации помещаются в 25 МБ :P)

Обратите внимание, что я не уверен на 100%, что переопределение методов экземпляра не сопровождается неясной регрессией поиска метода, поэтому, если у вас есть контроль над созданием экземпляра session, вероятно, безопаснее просто создать класс, который наследуется от HashWithIndifferentAccess с 2 переопределяет суть, а затем создает его экземпляр вместо хэш-класса по умолчанию, но на самом деле не беспокойтесь об этом, если вы не ожидаете действительно серьезного трафика.

person bbozo    schedule 10.08.2015