Skip to content

Instantly share code, notes, and snippets.

@jperry
Last active February 8, 2023 15:48
Show Gist options
  • Save jperry/a3fb9e39c2de19974b1a to your computer and use it in GitHub Desktop.
Save jperry/a3fb9e39c2de19974b1a to your computer and use it in GitHub Desktop.
Devise and warden remote authentication
module Devise
module Models
module RemoteAuthenticatable
extend ActiveSupport::Concern
#
# Here you do the request to the external webservice
#
# If the authentication is successful you should return
# a resource instance
#
# If the authentication fails you should return false
#
def remote_authentication(authentication_hash)
params = {
'username' => authentication_hash[:email],
'password' => authentication_hash[:password],
'client_id' => 'myclient',
'grant_type' => 'password'
}
result = AuthClient.get_oauth_token(params)
return false unless result.success?
response = JSON.parse(result.response)
self.email = authentication_hash[:email]
self.auth_token = response['access_token']
self.refresh_token = response['refresh_token']
self.expires_at = Time.now + response['expires_in']
return self
end
module ClassMethods
def serialize_from_session(data, salt)
resource = self.new
resource.email = data['email']
resource.auth_token = data['auth_token']
resource.refresh_token = data['refresh_token']
resource.expires_at = data['expires_at']
resource
end
def serialize_into_session(record)
[
{
:email => record.email,
:auth_token => record.auth_token,
:refresh_token => record.refresh_token,
:expires_at => record.expires_at
},
nil
]
end
end
end
end
end
module Devise
module Strategies
class RemoteAuthenticatable < Authenticatable
#
# For an example check : https://github.com/plataformatec/devise/blob/master/lib/devise/strategies/database_authenticatable.rb
#
# Method called by warden to authenticate a resource.
#
def authenticate!
#
# authentication_hash doesn't include the password
#
auth_params = authentication_hash
auth_params[:password] = password
#
# mapping.to is a wrapper over the resource model
#
resource = mapping.to.new
return fail! unless resource
if validate(resource){ resource.remote_authentication(auth_params) }
success!(resource)
end
end
end
end
end
require_relative 'remote_authenticatable'
class User
include ActiveModel::Validations #required because some before_validations are defined in devise
extend ActiveModel::Callbacks #required to define callbacks
extend Devise::Models
attr_accessor :email,
:auth_token,
:refresh_token,
:expires_at
define_model_callbacks :validation #required by Devise
devise :remote_authenticatable, :timeoutable
# Latest devise tries to initialize this class with values
# ignore it for now
def initialize(options={})
end
end
@kayleiburke
Copy link

THANK YOU for posting this! I can't tell you how helpful this was!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment