Module: Signinable::ModelAdditions::ClassMethods

Defined in:
lib/signinable/model_additions.rb

Constant Summary collapse

ALLOWED_RESTRICTIONS =
%i[ip user_agent].freeze
DEFAULT_REFRESH_EXP =
7200
DEFAULT_JWT_EXP =
900

Instance Method Summary collapse

Instance Method Details

#authenticate_with_token(jwt, ip, user_agent) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/signinable/model_additions.rb', line 28

def authenticate_with_token(jwt, ip, user_agent)
  jwt_payload = extract_jwt_payload(jwt)
  return nil unless jwt_payload

  jwt = refresh_jwt(jwt_payload[:data], ip, user_agent) if jwt_payload[:expired]

  signinable = find_by(primary_key => jwt_payload[:data]['signinable_id'])
  return nil unless signinable

  signinable.jwt = jwt
  signinable
end

#expiration_periodObject



41
42
43
44
45
# File 'lib/signinable/model_additions.rb', line 41

def expiration_period
  return refresh_exp.call if refresh_exp.respond_to?(:call)

  refresh_exp
end

#extract_jwt_payload(jwt) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/signinable/model_additions.rb', line 77

def extract_jwt_payload(jwt)
  {
    data: JWT.decode(jwt, jwt_secret, true, { algorithm: 'HS256' })[0],
    expired: false
  }
rescue JWT::DecodeError
  begin
    {
      data: JWT.decode(jwt, jwt_secret, true, { verify_expiration: false, algorithm: 'HS256' })[0],
      expired: true
    }
  rescue JWT::DecodeError
    nil
  end
end

#generate_jwt(refresh_token, signinable_id) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/signinable/model_additions.rb', line 47

def generate_jwt(refresh_token, signinable_id)
  JWT.encode(
    {
      refresh_token: refresh_token,
      signinable_id: signinable_id,
      exp: Time.zone.now.to_i + jwt_exp
    },
    jwt_secret,
    'HS256'
  )
end

#refresh_jwt(jwt_payload, ip, user_agent) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/signinable/model_additions.rb', line 59

def refresh_jwt(jwt_payload, ip, user_agent)
  old_token = jwt_payload['refresh_token']
  new_token = Signin.generate_token

  result = Signin.where(token: old_token)
                 .active
                 .update_all(
                   token: new_token,
                   expiration_time: expiration_period.seconds.from_now,
                   ip: ip,
                   user_agent: user_agent
                 )

  return if result.zero?

  generate_jwt(new_token, jwt_payload['signinable_id'])
end

#signinable(options = {}) ⇒ Object



17
18
19
20
21
22
23
24
25
26
# File 'lib/signinable/model_additions.rb', line 17

def signinable(options = {})
  self.refresh_exp = options.fetch(:refresh_exp, DEFAULT_REFRESH_EXP)
  self.simultaneous_signings = options.fetch(:simultaneous, true)
  self.jwt_secret = options.fetch(:jwt_secret)
  self.jwt_exp = options.fetch(:jwt_exp, DEFAULT_JWT_EXP)

  has_many :signins, as: :signinable, dependent: :destroy

  attr_accessor :jwt
end