apps/web/application.rb
controller.prepare do
use YourApp::WardenImpl::WebManager
include YourApp::WardenImpl::WardenHelper
authentication_via :web_strategy
auth_failure_to "/login"
before :authenticate! # run an authentication before callback
end
apps/api/v1/application.rb
controller.prepare do
use YourApp::WardenImpl::ApiManager
include YourApp::WardenImpl::WardenHelper
auth_failure_to "/api/v1/unauthenticated"
before :authenticate! # run an authentication before callback
end
lib/your_app/warden_impl/web_manager.rb
module YourApp
module WardenImpl
class WebManager < ::Warden::Manager
def initialize(app, options={})
super(app, options)
Warden::Strategies.add(:web_strategy, YourApp::WardenImpl::WebStrategy)
config.scope_defaults :default, strategies: [:web_strategy], action: "login"
config.failure_app = app
Warden::Manager.before_failure do |env, opts|
env['REQUEST_METHOD'] = "POST"
end
end
end
end
end
lib/your_app/warden_impl/web_strategy.rb
module YourApp
module WardenImpl
class WebStrategy < ::Warden::Strategies::Base
include Hashie::Extensions::SymbolizeKeys
include Hashie::Extensions::DeepFind
def request_params
@request_params ||= Hashie.symbolize_keys!(params).extend(Hashie::Extensions::DeepFind)
end
def user_params(key)
request_params.deep_find(key)
end
def valid?
!user_params(:username).blank? && !user_params(:password).blank?
end
def authenticate!
context.username = user_params(:username)
context.password = client_params(:password)
authenticate_user.call(context) # This is an injected Interactor from Collective Idea ;)
context.success? ? success!(context.output) : redirect!("/login?login_attempt=1")
end
end
end
end
lib/your_app/warden_impl/api_manager.rb
module YourApp
module WardenImpl
class ApiManager < ::Warden::Manager
def initialize(app, options={})
super(app, options)
Warden::Strategies.add(:access_token, YourApp::WardenImpl::AccessTokenStrategy)
config.scope_defaults :default, strategies: [:access_token]
config.failure_app = app
Warden::Manager.before_failure do |env, opts|
env['REQUEST_METHOD'] = "POST"
end
end
end
end
end
lib/your_app/warden_impl/access_token_strategy.rb
module YourApp
module WardenImpl
class AccessTokenStrategy < ::Warden::Strategies::Base
def valid?
access_token = request.env["HTTP_ACCESS_TOKEN"]
access_token.is_a?(String) && !access_token.blank?
end
def authenticate!
context.token = request.env["HTTP_ACCESS_TOKEN"]
authenticate_access_token.call(context) #Another collectiveidea interactor!
context.success? ? success!(context.output) : fail!("Could not log in")
end
end
end
end
lib/your_app/warden_impl/warden_helper.rb
module YourApp
module WardenImpl
module WardenHelper
def self.included(base)
base.extend ClassMethods
end
def authenticate!
unless ignored_classes.include?(self.class)
signin!
end
end
def authenticated?
request.env["warden"].authenticated?
end
def signin!
request.env["warden"].authenticate!(strategy)
rescue
redirect_to auth_failure_path unless auth_failure_path.blank?
end
def logout!
request.env["warden"].logout
end
def ignored_classes
@ignored_classes ||= [].tap do |result|
self.class.ignored_classes.each do |klass|
result.push(klass)
end
end
end
def strategy
@strategy = self.class.strategy!
end
def auth_failure_path
@auth_failure_path = self.class.auth_failure_path
end
def current_user!
request.env["warden"].user
end
module ClassMethods
def ignore_authentication!
class_eval do
ignored_classes.push(self)
end
end
def authentication_via(strategy)
@strategy = strategy
end
def strategy!
@strategy
end
def auth_failure_to(path)
@auth_failure_path = path
end
def auth_failure_path
@auth_failure_path
end
def ignored_classes
@ignored_classes ||= []
end
end
end
end
end