Skip to content

Commit

Permalink
Avoid tokens conflicts.
Browse files Browse the repository at this point in the history
  • Loading branch information
rjurado01 committed Jul 10, 2021
1 parent 8e6f1ff commit 6dc9f74
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 5 deletions.
11 changes: 9 additions & 2 deletions app/models/concerns/rails_jwt_auth/confirmable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def send_confirmation_instructions
return false
end

self.confirmation_token = SecureRandom.base58(24)
self.confirmation_token = generate_confirmation_token
self.confirmation_sent_at = Time.current
return false unless save

Expand Down Expand Up @@ -79,7 +79,7 @@ def update_email(params)
end

self.email = params[email_field]
self.confirmation_token = SecureRandom.base58(24)
self.confirmation_token = generate_confirmation_token
self.confirmation_sent_at = Time.current

valid? # validates first other fields
Expand All @@ -101,6 +101,13 @@ def update_email(params)

protected

def generate_confirmation_token
loop do
token = RailsJwtAuth.friendly_token
return token unless self.class.where(confirmation_token: token).exists?
end
end

def validate_confirmation
return true unless confirmed_at

Expand Down
11 changes: 10 additions & 1 deletion app/models/concerns/rails_jwt_auth/invitable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def invite
end

@inviting = true
self.invitation_token = RailsJwtAuth.friendly_token
self.invitation_token = generate_invitation_token
self.invitation_sent_at = Time.current

return false unless save_without_password
Expand Down Expand Up @@ -86,5 +86,14 @@ def expired_invitation_token?

invitation_sent_at && invitation_sent_at < expiration_time.ago
end

protected

def generate_invitation_token
loop do
token = RailsJwtAuth.friendly_token
return token unless self.class.where(invitation_token: token).exists?
end
end
end
end
11 changes: 10 additions & 1 deletion app/models/concerns/rails_jwt_auth/lockable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def failed_attempt
protected

def send_unlock_instructions
self.unlock_token = SecureRandom.base58(24)
self.unlock_token = generate_unlock_token
save(validate: false)

RailsJwtAuth.send_email(:unlock_instructions, self)
Expand Down Expand Up @@ -85,6 +85,15 @@ def attempts_expired?
first_failed_attempt_at && first_failed_attempt_at < RailsJwtAuth.reset_attempts_in.ago
end

protected

def generate_unlock_token
loop do
token = RailsJwtAuth.friendly_token
return token unless self.class.where(unlock_token: token).exists?
end
end

def lock_strategy_enabled?(strategy)
RailsJwtAuth.lock_strategy == strategy
end
Expand Down
11 changes: 10 additions & 1 deletion app/models/concerns/rails_jwt_auth/recoverable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def send_reset_password_instructions
return false
end

self.reset_password_token = RailsJwtAuth.friendly_token
self.reset_password_token = generate_reset_password_token
self.reset_password_sent_at = Time.current
return false unless save

Expand Down Expand Up @@ -59,5 +59,14 @@ def clean_reset_password
self.reset_password_sent_at = nil
self.reset_password_token = nil
end

protected

def generate_reset_password_token
loop do
token = RailsJwtAuth.friendly_token
return token unless self.class.where(reset_password_token: token).exists?
end
end
end
end
17 changes: 17 additions & 0 deletions spec/models/concerns/confirmable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@
expect(unconfirmed_user.confirmation_sent_at).not_to be_nil
end

it 'avoid to repeat token' do
other_user = FactoryBot.create("#{orm.underscore}_user")
other_user.update(confirmation_token: 'xxx')
allow(RailsJwtAuth).to receive(:friendly_token).and_return('xxx', 'yyy')

expect(unconfirmed_user.confirmation_token).to eq('yyy')
end

it 'sends confirmation email' do
new_user = FactoryBot.build("#{orm.underscore}_unconfirmed_user")
expect(RailsJwtAuth).to receive(:send_email).with(:confirmation_instructions, new_user)
Expand Down Expand Up @@ -116,6 +124,15 @@
expect(user.confirmation_sent_at).not_to be_nil
end

it 'avoid to repeat token' do
allow(RailsJwtAuth).to receive(:friendly_token).and_return('xxx', 'yyy')
expect(unconfirmed_user.confirmation_token).to eq('xxx')

expect(user.update_email(email: '[email protected]', password: password)).to be_truthy
expect(user.reload.unconfirmed_email).to eq('[email protected]')
expect(user.confirmation_token).to eq('yyy')
end

it 'checks email' do
expect(user.update_email(email: '')).to be_falsey
expect(get_record_error(user, :email)).to eq(:blank)
Expand Down
8 changes: 8 additions & 0 deletions spec/models/concerns/invitable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@
expect(@user.invitation_accepted_at).to be_nil
end

it 'avoid to repeat token' do
other_user = FactoryBot.create("#{orm.underscore}_user")
other_user.update(invitation_token: 'xxx')
allow(RailsJwtAuth).to receive(:friendly_token).and_return('xxx', 'yyy')

expect(invited_user.invitation_token).to eq('yyy')
end

it 'sends new invitation mail' do
expect(ActionMailer::Base.deliveries.count).to eq(1)
end
Expand Down
10 changes: 10 additions & 0 deletions spec/models/concerns/lockable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
user.lock_access
expect(user.locked_at).not_to be_nil
end

it 'avoid to repeat token' do
other_user = FactoryBot.create("#{orm.underscore}_user")
other_user.update(unlock_token: 'xxx')
allow(RailsJwtAuth).to receive(:friendly_token).and_return('xxx', 'yyy')

allow(user).to receive(:unlock_strategy_enabled?).and_return(true)
user.lock_access
expect(user.unlock_token).to eq('yyy')
end
end

%i[email both].each do |unlock_strategy|
Expand Down
10 changes: 10 additions & 0 deletions spec/models/concerns/recoverable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@
expect(user.reset_password_sent_at).not_to be_nil
end

it 'avoid to repeat token' do
other_user = FactoryBot.create("#{orm.underscore}_user")
other_user.update(reset_password_token: 'xxx')
allow(RailsJwtAuth).to receive(:friendly_token).and_return('xxx', 'yyy')

user.send_reset_password_instructions
user.reload
expect(user.reset_password_token).to eq('yyy')
end

it 'sends reset password email' do
expect(RailsJwtAuth).to receive(:send_email).with(:reset_password_instructions, user)
user.send_reset_password_instructions
Expand Down

0 comments on commit 6dc9f74

Please sign in to comment.