Class: SpreeCmCommissioner::UserAuthenticator

Inherits:
Object
  • Object
show all
Defined in:
app/services/spree_cm_commissioner/user_authenticator.rb

Class Method Summary collapse

Class Method Details

.auth_context(params) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'app/services/spree_cm_commissioner/user_authenticator.rb', line 33

def self.auth_context(params)
  oauth_application = find_oauth_application(params)
  tenant_id = oauth_application&.tenant_id

  case flow_type(params)
  when 'load_test_auth'
    # k6 sends the load-test JWT as `user_id_token`; internally it's a login_token (see
    # UserPasswordAuthenticator's self-identifying, token-only path).
    options = { login_token: params[:user_id_token], tenant_id: tenant_id }
    SpreeCmCommissioner::UserPasswordAuthenticator.call(options)
  when 'login_auth'
    options = { login: params[:username], password: params[:password], tenant_id: tenant_id }
    SpreeCmCommissioner::UserPasswordAuthenticator.call(options)
  when 'telegram_oauth_auth'
    options = { id_token: params[:telegram_id_token], tenant_id: tenant_id }
    SpreeCmCommissioner::UserTelegramOauthAuthenticator.call(options)
  when 'social_auth'
    options = { id_token: params[:id_token], tenant_id: tenant_id }
    SpreeCmCommissioner::UserIdTokenAuthenticator.call(options)
  when 'facebook_auth'
    options = { fb_access_token: params[:fb_access_token], tenant_id: tenant_id }
    SpreeCmCommissioner::UserFbTokenAuthenticator.call(options)
  when 'telegram_web_app_auth'
    options = { telegram_init_data: params[:telegram_init_data], telegram_bot_username: params[:tg_bot] }
    SpreeCmCommissioner::UserTelegramWebAppAuthenticator.call(options)
  when 'vattanac_bank_web_app_auth'
    options = { session_id: params[:session_id] }
    SpreeCmCommissioner::UserVattanacBankWebAppAuthenticator.call(options)
  end
end

.call!(params) ⇒ Object

:username, :password :id_token (Firebase social login) :telegram_id_token -> Telegram OIDC login (Firebase/Google social login) :user_id_token (load-test JWT, self-identifying, minted by LoadTest::LoginToken) :fb_access_token :telegram_init_data, :tg_bot :session_id



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'app/services/spree_cm_commissioner/user_authenticator.rb', line 12

def self.call!(params)
  context = auth_context(params)
  raise exception(context.message) unless context.success?

  user = context.user

  # Check if user.tenant_id is nil first to keep our old logic work as usual
  if user.tenant_id.nil? && params[:client_id].blank? && params[:client_secret].blank?
    return user
  elsif params[:client_id].present? && params[:client_secret].present?
    oauth_application = find_oauth_application(params)
    raise exception(I18n.t('authenticator.invalid_client_credentials')) unless oauth_application

    validate_tenant_match!(user, oauth_application)
  else
    raise exception(I18n.t('authenticator.invalid_or_missing_params'))
  end

  user
end

.exception(message) ⇒ Object



85
86
87
# File 'app/services/spree_cm_commissioner/user_authenticator.rb', line 85

def self.exception(message)
  Doorkeeper::Errors::DoorkeeperError.new(message)
end

.find_oauth_application(params) ⇒ Object



95
96
97
# File 'app/services/spree_cm_commissioner/user_authenticator.rb', line 95

def self.find_oauth_application(params)
  Spree::OauthApplication.find_by(uid: params[:client_id], secret: params[:client_secret])
end

.flow_type(params) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'app/services/spree_cm_commissioner/user_authenticator.rb', line 64

def self.flow_type(params)
  # A separate params key from `id_token` (social login) means we only ever attempt to decode
  # a token that's actually claiming to be a load-test token, instead of decoding every
  # request's id_token to find out.
  return 'load_test_auth' if load_test_id_token?(params[:user_id_token])
  return 'login_auth' if params.key?(:username) && params.key?(:password)
  return 'telegram_oauth_auth' if params[:telegram_id_token].present?
  return 'social_auth' if params.key?(:id_token)
  return 'facebook_auth' if params.key?(:fb_access_token)
  return 'telegram_web_app_auth' if params.key?(:telegram_init_data) && params.key?(:tg_bot)
  return 'vattanac_bank_web_app_auth' if params.key?(:session_id)

  raise exception(I18n.t('authenticator.invalid_or_missing_params'))
end

.load_test_id_token?(token) ⇒ Boolean

True only for a load-test id_token — it's signed with our own secret, so it decodes here whereas a real Firebase/Google id_token (RS256, Google's keys) returns nil.

Returns:

  • (Boolean)


81
82
83
# File 'app/services/spree_cm_commissioner/user_authenticator.rb', line 81

def self.load_test_id_token?(token)
  token.present? && SpreeCmCommissioner::LoadTest::LoginToken.decode(token).present?
end

.validate_tenant_match!(user, oauth_application) ⇒ Object

Raises:

  • (ActiveRecord::RecordNotFound)


89
90
91
92
93
# File 'app/services/spree_cm_commissioner/user_authenticator.rb', line 89

def self.validate_tenant_match!(user, oauth_application)
  return if user.tenant_id == oauth_application.tenant_id

  raise ActiveRecord::RecordNotFound
end