Skip to content

Commit 3e46396

Browse files
committed
Fix test for maximum concurrent devices.
1 parent d7aaa80 commit 3e46396

File tree

3 files changed

+31
-15
lines changed

3 files changed

+31
-15
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ The following settings are available for configuration in `config/initializers/d
176176
|---|---|---|
177177
| **`change_headers_on_each_request`** | `true` | By default the access-token header will change after each request. The client is responsible for keeping track of the changing tokens. Both [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) and [jToker](https://github.com/lynndylanhurley/j-toker) do this out of the box. While this implementation is more secure, it can be difficult to manage. Set this to false to prevent the `access-token` header from changing after each request. [Read more](#about-token-management). |
178178
| **`token_lifespan`** | `2.weeks` | Set the length of your tokens' lifespans. Users will need to re-authenticate after this duration of time has passed since their last login. |
179+
| **`max_number_of_devices`** | `10` | Set the max number of concurrent devices per user. After this limit is reached, the oldest tokens will be removed. |
179180
| **`batch_request_buffer_throttle`** | `5.seconds` | Sometimes it's necessary to make several requests to the API at the same time. In this case, each request in the batch will need to share the same auth token. This setting determines how far apart the requests can be while still using the same auth token. [Read more](#about-batch-requests). |
180181
| **`omniauth_prefix`** | `"/omniauth"` | This route will be the prefix for all oauth2 redirect callbacks. For example, using the default '/omniauth' setting, the github oauth2 provider will redirect successful authentications to '/omniauth/github/callback'. [Read more](#omniauth-provider-settings). |
181182
| **`default_confirm_success_url`** | `nil` | By default this value is expected to be sent by the client so that the API knows where to redirect users after successful email confirmation. If this param is set, the API will redirect to this value when no value is provided by the client. |

app/controllers/devise_token_auth/concerns/set_user_by_token.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ def set_user_by_token(mapping=nil)
6262
if devise_warden_user && devise_warden_user.tokens[@client_id].nil?
6363
@used_auth_by_token = false
6464
@resource = devise_warden_user
65-
# REVIEW: Why are we bothering to create an auth token here? It won't
66-
# get used anywhere by the looks of it...?
67-
@resource.create_new_auth_token
6865
end
6966
end
7067

test/controllers/demo_user_controller_test.rb

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,34 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
412412
DeviseTokenAuth.headers_names[:'access-token'] = 'access-token'
413413
end
414414
end
415+
416+
describe 'maximum concurrent devices per user' do
417+
before do
418+
@max_devices = DeviseTokenAuth.max_number_of_devices
419+
end
420+
421+
it 'should limit the maximum number of concurrent devices' do
422+
# increment the number of devices until the maximum is exceeded
423+
1.upto(@max_devices + 1).each do |n|
424+
assert_equal [n, @max_devices].min, @resource.reload.tokens.keys.length
425+
@resource.create_new_auth_token
426+
end
427+
end
428+
429+
it 'should drop the oldest token when the maximum number of devices is exceeded' do
430+
# create the maximum number of tokens
431+
1.upto(@max_devices).each { @resource.create_new_auth_token }
432+
433+
# get the oldest token
434+
oldest_token, _ = @resource.reload.tokens \
435+
.min_by { |cid, v| v[:expiry] || v["expiry"] }
436+
437+
# create another token, thereby dropping the oldest token
438+
@resource.create_new_auth_token
439+
440+
assert_not_includes @resource.reload.tokens.keys, oldest_token
441+
end
442+
end
415443
end
416444

417445
describe 'bypass_sign_in' do
@@ -508,18 +536,6 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
508536
it 'should not define current_mang' do
509537
refute_equal @resource, @controller.current_mang
510538
end
511-
512-
it 'should increase the number of tokens by a factor of 2 up to 11' do
513-
@first_token = @resource.tokens.keys.first
514-
515-
DeviseTokenAuth.max_number_of_devices = 11
516-
(1..10).each do |n|
517-
assert_equal [11, 2 * n].min, @resource.reload.tokens.keys.length
518-
get '/demo/members_only', params: {}, headers: nil
519-
end
520-
521-
assert_not_includes @resource.reload.tokens.keys, @first_token
522-
end
523539
end
524540

525541
it 'should return success status' do
@@ -554,6 +570,8 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
554570
@resource.save!
555571
login_as(@resource, scope: :user)
556572

573+
# send the auth_headers anyway, but they *should* be ignored and
574+
# warden *should* still authenticate correctly.
557575
get '/demo/members_only',
558576
params: {},
559577
headers: @auth_headers

0 commit comments

Comments
 (0)