module SimpleMobileOauth::Authenticator

SimpleMobileOauth::Authenticator

Scenarios:

  1. if identity with uid and provider exists

    1. if user param is given

      1. if identity’s owner matches the user param, it returns the identity’s owner

      2. else it raises error because the identity exists with another user

    2. if user param is not given (so it’s a log in), it returns the identity’s owner

  2. if identity is not found by given oauth

    1. if user_param is not given, then we return nil (most likely in mid of registration phase)

    2. if user param is given

      1. if user can be found by user_param, it creates the binds the identity to that user

      2. if user can not be found by user param, it creates both user and identity (registration)

Usage example:

class UserAuthenticator
  include SimpleMobileOauth::Authenticator

  find_identity do |params|
    Identity.find_by params.merge(identifiable_type: 'User')
  end

  find_user do |params|
    return nil unless params.present?
    User.find_by email: params['email']
  end

  build_user do |params|
    raise ArgumentError, 'missing params' unless params
    attrs = {email: params['email'], password: Devise.friendly_token[0,20]}
    User.new(attrs)
  end
end

user = UserAuthenticator.new.call(params)

Constants

BaseError
IdentityAlreadyBoundError
IdentityMissingOwnerError
InvalidParamsError

Public Instance Methods

call(params) click to toggle source
# File lib/simple_mobile_oauth/authenticator.rb, line 73
def call(params)
  oauth_params    = params.fetch('auth')           { raise InvalidParamsError, "auth param is missing" }
  oauth_uid       = oauth_params.fetch('uid')      { raise InvalidParamsError, "uid is missing"        }
  oauth_provider  = oauth_params.fetch('provider') { raise InvalidParamsError, "provider is missing"   }
  oauth_info      = oauth_params.fetch('info')     { {} }
  user_params     = params['user']
  identity_params = { uid: oauth_uid, provider: oauth_provider, info: oauth_info }
  identity        = _find_identity_strategy(identity_params.slice(:uid, :provider))

  return EmptyUser.new if start_of_registration_process?(identity, user_params)

  if identity
    identity_owner = identity.identifiable
    raise IdentityMissingOwnerError, 'internal error' unless identity_owner

    return identity_owner if login_request?(identity_owner, user_params)

    user = _find_user_strategy(user_params)
    raise InvalidParamsError, 'could not find user from params given' unless user
    raise IdentityAlreadyBoundError, 'oauth identity exists with another user' \
      if identity_already_bound_to_different_user?(identity_owner, user)

      # So the identity owner and user found from param match
    user
  else
    raise InvalidParamsError, 'missing user params' unless user_params

    user = _find_user_strategy(user_params) || _build_user_strategy(user_params)

    user.identities.build(identity_params)
    user.save
    user
  end
end

Private Instance Methods

identity_already_bound_to_different_user?(identity_owner, user) click to toggle source
# File lib/simple_mobile_oauth/authenticator.rb, line 114
def identity_already_bound_to_different_user?(identity_owner, user)
  identity_owner && user && identity_owner != user
end
login_request?(identity_owner, user_params) click to toggle source
# File lib/simple_mobile_oauth/authenticator.rb, line 110
def login_request?(identity_owner, user_params)
  identity_owner && !user_params
end
start_of_registration_process?(identity, user_params) click to toggle source
# File lib/simple_mobile_oauth/authenticator.rb, line 118
def start_of_registration_process?(identity, user_params)
  !identity && !user_params
end