devise_jwt_auth 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -56
- data/app/controllers/devise_jwt_auth/sessions_controller.rb +5 -1
- data/app/controllers/devise_jwt_auth/unlocks_controller.rb +2 -10
- data/lib/devise_jwt_auth/version.rb +1 -1
- data/test/controllers/devise_jwt_auth/registrations_controller_test.rb +1 -18
- data/test/controllers/devise_jwt_auth/sessions_controller_test.rb +72 -54
- data/test/controllers/devise_jwt_auth/unlocks_controller_test.rb +4 -18
- data/test/dummy/app/controllers/overrides/sessions_controller.rb +2 -2
- metadata +2 -10
- data/test/dummy/tmp/generators/app/models/user.rb +0 -9
- data/test/dummy/tmp/generators/config/initializers/devise_jwt_auth.rb +0 -74
- data/test/dummy/tmp/generators/config/routes.rb +0 -4
- data/test/dummy/tmp/generators/db/migrate/20200206224309_devise_jwt_auth_create_users.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5696b7fd28731ae8f1b92ea62e27e19849e338414f2ceb3e4c34f8d0f9d01bb1
|
4
|
+
data.tar.gz: 8c87dbf4b8fd5fc5042f5ad43bbddcd1f779f0fac58731df84376c060f1f368a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5000f849307719199b1b8de4495bc6f283fff8e0f24da5e6bc61020552789886479ad99c81458083824232b6519f97b2913bbd768c73a7eae2f1525480fad509
|
7
|
+
data.tar.gz: a1ee99b078d18ebda654ba0eb64922b8b0449dc90c3794ca72d76cac38ae1d948cafa962531087020d58d49862287c9ba7b955e7d6f5056fa9447f267f3298d4
|
data/README.md
CHANGED
@@ -1,34 +1,30 @@
|
|
1
|
-
# Devise
|
1
|
+
# Devise Jwt Auth
|
2
2
|
|
3
|
-
[
|
4
|
-
[![Build Status](https://travis-ci.org/lynndylanhurley/devise_jwt_auth.svg?branch=master)](https://travis-ci.org/lynndylanhurley/devise_jwt_auth)
|
5
|
-
[![Code Climate](https://codeclimate.com/github/lynndylanhurley/devise_jwt_auth/badges/gpa.svg)](https://codeclimate.com/github/lynndylanhurley/devise_jwt_auth)
|
6
|
-
[![Test Coverage](https://codeclimate.com/github/lynndylanhurley/devise_jwt_auth/badges/coverage.svg)](https://codeclimate.com/github/lynndylanhurley/devise_jwt_auth/coverage)
|
7
|
-
[![Downloads](https://img.shields.io/gem/dt/devise_jwt_auth.svg)](https://rubygems.org/gems/devise_jwt_auth)
|
8
|
-
[![Backers on Open Collective](https://opencollective.com/devise_jwt_auth/backers/badge.svg)](#backers)
|
9
|
-
[![Sponsors on Open Collective](https://opencollective.com/devise_jwt_auth/sponsors/badge.svg)](#sponsors)
|
10
|
-
[![Join the chat at https://gitter.im/lynndylanhurley/devise_jwt_auth](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lynndylanhurley/devise_jwt_auth?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
3
|
+
A JWT-based port of [Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth) with silent refresh support.
|
11
4
|
|
12
|
-
|
5
|
+
If you're building SPA or a mobile app, this library takes an JWT token approach to authentication. If you're new to how JWTs (pronounced 'jot') work, you can read up on them [here](https://jwt.io/introduction/). This library is designed with an access/refresh token model in mind.
|
13
6
|
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
## How does silent refresh authentication work?
|
8
|
+
|
9
|
+
When a user is authenticated, an access token is sent in the response and usually in the body in the form of JSON data. These tokens are designed to last a "short" time - only about 15 minutes. What you do with these tokens is up to you, but the best practice is to keep these tokens in memory and NOT to store them as cookies or in local storage. That way they cannot be used in XSS or CSRF attacks. The access tokens are then sent as headers in requests when an authenticated user is required to access protected resources.
|
10
|
+
|
11
|
+
The downside here is that the user will need to reauthenticate themselves frequently and if the user reloads their browser, the access token disappears and the user is no longer authenticated. This is where refresh tokens come into play.
|
12
|
+
|
13
|
+
Refresh tokens are different than access tokens in the fact that they are sent as HTTP only cookies that cannot be accessed using Javascript. These tokens are expected to last a "long" time - a fews days or maybe a week. When the user's access token expires, or the user reloads the page, these tokens persist and then are used for the sole purpose of requesting new access tokens.
|
14
|
+
|
15
|
+
An additional feature can allow you to invalidate all the user's tokens by implementing a token version number. Anytime that user changes their password or their security roles change or if they choose to log out of all of their devices, updating the user's token version (usually in the form of incrementing its value) will invalidate all of the user's tokens in the wild. The way this works is by including the user's token version in the JWT payload so when the server authenticates a user, the user is found not only by their `uid` but also their `token_version`.
|
16
|
+
|
17
|
+
*Note:* Token versions are not currently supported by this library but will be in the near future.
|
17
18
|
|
18
19
|
## Main features
|
19
20
|
|
20
|
-
* Seamless integration with:
|
21
|
-
* [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) for [AngularJS](https://github.com/angular/angular.js)
|
22
|
-
* [Angular-Token](https://github.com/neroniaky/angular-token) for [Angular](https://github.com/angular/angular)
|
23
|
-
* [redux-token-auth](https://github.com/kylecorbelli/redux-token-auth) for [React with Redux](https://github.com/reactjs/react-redux)
|
24
|
-
* [jToker](https://github.com/lynndylanhurley/j-toker) for [jQuery](https://jquery.com/)
|
25
21
|
* Oauth2 authentication using [OmniAuth](https://github.com/intridea/omniauth).
|
26
22
|
* Email authentication using [Devise](https://github.com/plataformatec/devise), including:
|
27
23
|
* User registration, update and deletion
|
28
24
|
* Login and logout
|
29
25
|
* Password reset, account confirmation
|
30
|
-
* Support for
|
31
|
-
* It is
|
26
|
+
* Support for multiple user models.
|
27
|
+
* It is secure.
|
32
28
|
|
33
29
|
This project leverages the following gems:
|
34
30
|
|
@@ -49,51 +45,20 @@ Then install the gem using bundle:
|
|
49
45
|
bundle install
|
50
46
|
~~~
|
51
47
|
|
52
|
-
|
48
|
+
More documentation will come later as this project progresses.
|
53
49
|
|
54
50
|
## Need help?
|
55
51
|
|
56
|
-
|
57
|
-
|
58
|
-
Please open GitHub issues for bugs and enhancements only, not general help requests. Please search previous issues (and Google and StackOverflow) before creating a new issue.
|
59
|
-
|
60
|
-
Please read the [issue template](https://github.com/lynndylanhurley/devise_jwt_auth/blob/master/.github/ISSUE_TEMPLATE.md) before posting issues.
|
61
|
-
|
62
|
-
## [FAQ](docs/faq.md)
|
52
|
+
As this library is fairly new there will be some issues until it matures. Please feel free to post questions here and contributers are also welcome, especially if you have knowledge with continuous integration as I'm fairly new to that and as this is a port of DTA, I'm in the process of configuring the project with its own settings.
|
63
53
|
|
64
54
|
## Contributors wanted!
|
65
55
|
|
66
|
-
See our [Contribution Guidelines](https://github.com/
|
67
|
-
|
68
|
-
We have some bounties for some issues, [check them out](https://github.com/lynndylanhurley/devise_jwt_auth/issues?q=is%3Aopen+is%3Aissue+label%3Abounty)!
|
56
|
+
See our [Contribution Guidelines](https://github.com/aarona/devise_jwt_auth/blob/master/.github/CONTRIBUTING.md). Feel free to submit pull requests, review pull requests, or review open issues. If you'd like to get in contact, you can reach me [here](https://github.com/aarona/).
|
69
57
|
|
70
58
|
## Live Demos
|
71
59
|
|
72
|
-
|
73
|
-
|
74
|
-
[Here is a demo](https://stackblitz.com/github/neroniaky/angular-token) of this app running with the [Angular-Token](https://github.com/neroniaky/angular-token) service and [Angular](https://github.com/angular/angular).
|
75
|
-
|
76
|
-
[Here is a demo](https://j-toker-demo.herokuapp.com/) of this app using the [jToker](https://github.com/lynndylanhurley/j-toker) plugin and [React](http://facebook.github.io/react/).
|
77
|
-
|
78
|
-
The fully configured api used in these demos can be found [here](https://github.com/lynndylanhurley/devise_jwt_auth_demo).
|
79
|
-
|
80
|
-
|
81
|
-
## Contributors
|
82
|
-
|
83
|
-
<a href="graphs/contributors"><img src="https://opencollective.com/devise_jwt_auth/contributors.svg?width=890&button=false" /></a>
|
84
|
-
|
85
|
-
## Backers
|
86
|
-
|
87
|
-
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/devise_jwt_auth#backer)]
|
88
|
-
|
89
|
-
[![](https://opencollective.com/devise_jwt_auth/backers.svg?width=890)](https://opencollective.com/devise_jwt_auth#backers)
|
90
|
-
|
91
|
-
|
92
|
-
## Sponsors
|
93
|
-
|
94
|
-
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/devise_jwt_auth#sponsor)]
|
95
|
-
|
96
|
-
[![](https://opencollective.com/devise_jwt_auth/sponsor/0/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/0/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/1/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/1/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/2/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/2/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/3/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/3/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/4/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/4/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/5/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/5/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/6/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/6/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/7/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/7/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/8/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/8/website) [![](https://opencollective.com/devise_jwt_auth/sponsor/9/avatar.svg)](https://opencollective.com/devise_jwt_auth/sponsor/9/website)
|
60
|
+
Live demos will hopefully be added in the future. At the very least, I'm planning on creating a Rails/React proof of concept repo that you can clone and run locally.
|
97
61
|
|
98
62
|
## License
|
63
|
+
|
99
64
|
This project uses the WTFPL
|
@@ -33,6 +33,7 @@ module DeviseJwtAuth
|
|
33
33
|
|
34
34
|
yield @resource if block_given?
|
35
35
|
|
36
|
+
update_refresh_token_cookie
|
36
37
|
render_create_success
|
37
38
|
elsif @resource && !(!@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?)
|
38
39
|
if @resource.respond_to?(:locked_at) && @resource.locked_at
|
@@ -46,6 +47,8 @@ module DeviseJwtAuth
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def destroy
|
50
|
+
# TODO: logout? update token version?
|
51
|
+
|
49
52
|
# remove auth instance variables so that after_action does not run
|
50
53
|
user = remove_instance_variable(:@resource) if @resource
|
51
54
|
# client = @token.client if @token.client
|
@@ -95,9 +98,10 @@ module DeviseJwtAuth
|
|
95
98
|
end
|
96
99
|
|
97
100
|
def render_create_success
|
101
|
+
auth_header = @resource.create_named_token_pair
|
98
102
|
render json: {
|
99
103
|
data: resource_data(resource_json: @resource.token_validation_response)
|
100
|
-
}
|
104
|
+
}.merge(auth_header)
|
101
105
|
end
|
102
106
|
|
103
107
|
def render_create_error_not_confirmed
|
@@ -35,25 +35,16 @@ module DeviseJwtAuth
|
|
35
35
|
@resource = resource_class.unlock_access_by_token(params[:unlock_token])
|
36
36
|
|
37
37
|
if @resource.persisted?
|
38
|
-
# token = @resource.create_token
|
39
|
-
# @resource.save!
|
40
38
|
yield @resource if block_given?
|
41
39
|
|
42
40
|
redirect_header_options = { unlock: true }
|
43
41
|
redirect_headers = @resource.create_named_token_pair.
|
44
42
|
merge(redirect_header_options)
|
45
43
|
|
46
|
-
# TODO: add a refresh token cookie in the response.
|
47
44
|
update_refresh_token_cookie
|
48
45
|
redirect_url = after_unlock_path_for(@resource)
|
49
46
|
redirect_to_link = DeviseJwtAuth::Url.generate(redirect_url, redirect_headers)
|
50
47
|
|
51
|
-
# redirect_headers = build_redirect_headers(token.token,
|
52
|
-
# token.client,
|
53
|
-
# redirect_header_options)
|
54
|
-
# redirect_to(@resource.build_auth_url(after_unlock_path_for(@resource),
|
55
|
-
# redirect_headers))
|
56
|
-
|
57
48
|
redirect_to redirect_to_link
|
58
49
|
else
|
59
50
|
render_show_error
|
@@ -62,7 +53,8 @@ module DeviseJwtAuth
|
|
62
53
|
|
63
54
|
private
|
64
55
|
def after_unlock_path_for(resource)
|
65
|
-
#TODO: This should probably be a configuration option at the very least.
|
56
|
+
# TODO: This should probably be a configuration option at the very least.
|
57
|
+
# Use confirmation controller / tests as a template for building out this feature.
|
66
58
|
'/'
|
67
59
|
end
|
68
60
|
|
@@ -176,7 +176,7 @@ class DeviseJwtAuth::RegistrationsControllerTest < ActionDispatch::IntegrationTe
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
-
describe 'failure if not
|
179
|
+
describe 'failure if not redirect_url' do
|
180
180
|
test 'request should fail if not redirect_url' do
|
181
181
|
post '/auth',
|
182
182
|
params: { email: Faker::Internet.email,
|
@@ -237,14 +237,6 @@ class DeviseJwtAuth::RegistrationsControllerTest < ActionDispatch::IntegrationTe
|
|
237
237
|
test 'email contains the default redirect url' do
|
238
238
|
assert_equal @redirect_url, @sent_redirect_url
|
239
239
|
end
|
240
|
-
|
241
|
-
test 'response should have an access token' do
|
242
|
-
assert @data[DeviseJwtAuth.access_token_name]
|
243
|
-
end
|
244
|
-
|
245
|
-
test 'response should have refresh token' do
|
246
|
-
assert response.cookies[DeviseJwtAuth.refresh_token_name]
|
247
|
-
end
|
248
240
|
end
|
249
241
|
|
250
242
|
describe 'using namespaces' do
|
@@ -260,7 +252,6 @@ class DeviseJwtAuth::RegistrationsControllerTest < ActionDispatch::IntegrationTe
|
|
260
252
|
}
|
261
253
|
|
262
254
|
@resource = assigns(:resource)
|
263
|
-
@data = JSON.parse(response.body)
|
264
255
|
@mail = ActionMailer::Base.deliveries.last
|
265
256
|
end
|
266
257
|
|
@@ -271,14 +262,6 @@ class DeviseJwtAuth::RegistrationsControllerTest < ActionDispatch::IntegrationTe
|
|
271
262
|
test 'user should have been created' do
|
272
263
|
assert @resource.id
|
273
264
|
end
|
274
|
-
|
275
|
-
test 'response should have an access token' do
|
276
|
-
assert @data[DeviseJwtAuth.access_token_name]
|
277
|
-
end
|
278
|
-
|
279
|
-
test 'response should have refresh token' do
|
280
|
-
assert response.cookies[DeviseJwtAuth.refresh_token_name]
|
281
|
-
end
|
282
265
|
end
|
283
266
|
|
284
267
|
describe 'case-insensitive email' do
|
@@ -13,7 +13,6 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
13
13
|
describe 'Confirmed user' do
|
14
14
|
before do
|
15
15
|
@existing_user = create(:user, :with_nickname, :confirmed)
|
16
|
-
@access_token_name = DeviseJwtAuth.access_token_name
|
17
16
|
end
|
18
17
|
|
19
18
|
describe 'success' do
|
@@ -35,57 +34,14 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
35
34
|
test 'request should return user data' do
|
36
35
|
assert_equal @existing_user.email, @data['data']['email']
|
37
36
|
end
|
38
|
-
=begin
|
39
|
-
describe "with multiple clients and headers don't change in each request" do
|
40
|
-
before do
|
41
|
-
# Set the max_number_of_devices to a lower number
|
42
|
-
# to expedite tests! (Default is 10)
|
43
|
-
DeviseJwtAuth.max_number_of_devices = 2
|
44
|
-
DeviseJwtAuth.change_headers_on_each_request = false
|
45
|
-
|
46
|
-
@user_session_params = {
|
47
|
-
email: @existing_user.email,
|
48
|
-
password: @existing_user.password
|
49
|
-
}
|
50
|
-
end
|
51
|
-
|
52
|
-
test 'should limit the maximum number of concurrent devices' do
|
53
|
-
# increment the number of devices until the maximum is exceeded
|
54
|
-
1.upto(DeviseJwtAuth.max_number_of_devices + 1).each do |n|
|
55
|
-
initial_tokens = @existing_user.reload.tokens
|
56
|
-
|
57
|
-
assert_equal(
|
58
|
-
[n, DeviseJwtAuth.max_number_of_devices].min,
|
59
|
-
@existing_user.reload.tokens.length
|
60
|
-
)
|
61
|
-
|
62
|
-
# Already have the max number of devices
|
63
|
-
post :create, params: @user_session_params
|
64
|
-
|
65
|
-
# A session for a new device maintains the max number of concurrent devices
|
66
|
-
refute_equal initial_tokens, @existing_user.reload.tokens
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
test 'should drop old tokens when max number of devices is exceeded' do
|
71
|
-
1.upto(DeviseJwtAuth.max_number_of_devices).each do |n|
|
72
|
-
post :create, params: @user_session_params
|
73
|
-
end
|
74
|
-
|
75
|
-
oldest_token, _ = @existing_user.reload.tokens \
|
76
|
-
.min_by { |cid, v| v[:expiry] || v['expiry'] }
|
77
|
-
|
78
|
-
post :create, params: @user_session_params
|
79
37
|
|
80
|
-
|
81
|
-
|
38
|
+
test 'response should have access token' do
|
39
|
+
assert @data[DeviseJwtAuth.access_token_name]
|
40
|
+
end
|
82
41
|
|
83
|
-
|
84
|
-
|
85
|
-
DeviseJwtAuth.change_headers_on_each_request = true
|
86
|
-
end
|
42
|
+
test 'response should have refresh token' do
|
43
|
+
assert response.cookies[DeviseJwtAuth.refresh_token_name]
|
87
44
|
end
|
88
|
-
=end
|
89
45
|
end
|
90
46
|
|
91
47
|
describe 'get sign_in is not supported' do
|
@@ -99,10 +55,19 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
99
55
|
test 'user is notified that they should use post sign_in to authenticate' do
|
100
56
|
assert_equal 405, response.status
|
101
57
|
end
|
58
|
+
|
102
59
|
test 'response should contain errors' do
|
103
60
|
assert @data['errors']
|
104
61
|
assert_equal @data['errors'], [I18n.t('devise_jwt_auth.sessions.not_supported')]
|
105
62
|
end
|
63
|
+
|
64
|
+
test 'response should not have access token' do
|
65
|
+
assert_nil @data[DeviseJwtAuth.access_token_name]
|
66
|
+
end
|
67
|
+
|
68
|
+
test 'response should not have refresh token' do
|
69
|
+
assert_nil response.cookies[DeviseJwtAuth.refresh_token_name]
|
70
|
+
end
|
106
71
|
end
|
107
72
|
|
108
73
|
describe 'header sign_in is supported' do
|
@@ -119,6 +84,14 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
119
84
|
test 'user can sign in using header request' do
|
120
85
|
assert_equal 200, response.status
|
121
86
|
end
|
87
|
+
|
88
|
+
test 'response should have access token' do
|
89
|
+
assert @data[DeviseJwtAuth.access_token_name]
|
90
|
+
end
|
91
|
+
|
92
|
+
test 'response should have refresh token' do
|
93
|
+
assert response.cookies[DeviseJwtAuth.refresh_token_name]
|
94
|
+
end
|
122
95
|
end
|
123
96
|
|
124
97
|
describe 'alt auth keys' do
|
@@ -133,6 +106,14 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
133
106
|
assert_equal 200, response.status
|
134
107
|
assert_equal @existing_user.email, @data['data']['email']
|
135
108
|
end
|
109
|
+
|
110
|
+
test 'response should have access token' do
|
111
|
+
assert @data[DeviseJwtAuth.access_token_name]
|
112
|
+
end
|
113
|
+
|
114
|
+
test 'response should have refresh token' do
|
115
|
+
assert response.cookies[DeviseJwtAuth.refresh_token_name]
|
116
|
+
end
|
136
117
|
end
|
137
118
|
|
138
119
|
describe 'authed user sign out' do
|
@@ -144,21 +125,25 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
144
125
|
def @controller.reset_session
|
145
126
|
@reset_session_called = true
|
146
127
|
end
|
128
|
+
|
147
129
|
@auth_headers = @existing_user.create_named_token_pair
|
148
130
|
|
149
131
|
request.headers.merge!(@auth_headers)
|
150
132
|
delete :destroy, format: :json
|
133
|
+
@data = JSON.parse(response.body)
|
151
134
|
end
|
152
135
|
|
153
136
|
test 'user is successfully logged out' do
|
154
137
|
assert_equal 200, response.status
|
155
138
|
end
|
156
|
-
|
157
|
-
test '
|
158
|
-
@
|
159
|
-
|
139
|
+
|
140
|
+
test 'response should not have access token' do
|
141
|
+
assert_nil @data[DeviseJwtAuth.access_token_name]
|
142
|
+
end
|
143
|
+
|
144
|
+
test 'response should not have refresh token' do
|
145
|
+
assert_nil response.cookies[DeviseJwtAuth.refresh_token_name]
|
160
146
|
end
|
161
|
-
=end
|
162
147
|
|
163
148
|
test 'session was destroyed' do
|
164
149
|
assert_equal true, @controller.reset_session_called
|
@@ -182,6 +167,14 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
182
167
|
assert_equal @data['errors'],
|
183
168
|
[I18n.t('devise_jwt_auth.sessions.user_not_found')]
|
184
169
|
end
|
170
|
+
|
171
|
+
test 'response should not have access token' do
|
172
|
+
assert_nil @data[DeviseJwtAuth.access_token_name]
|
173
|
+
end
|
174
|
+
|
175
|
+
test 'response should not have refresh token' do
|
176
|
+
assert_nil response.cookies[DeviseJwtAuth.refresh_token_name]
|
177
|
+
end
|
185
178
|
end
|
186
179
|
|
187
180
|
describe 'failure' do
|
@@ -203,6 +196,14 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
203
196
|
assert_equal @data['errors'],
|
204
197
|
[I18n.t('devise_jwt_auth.sessions.bad_credentials')]
|
205
198
|
end
|
199
|
+
|
200
|
+
test 'response should not have access token' do
|
201
|
+
assert_nil @data[DeviseJwtAuth.access_token_name]
|
202
|
+
end
|
203
|
+
|
204
|
+
test 'response should not have refresh token' do
|
205
|
+
assert_nil response.cookies[DeviseJwtAuth.refresh_token_name]
|
206
|
+
end
|
206
207
|
end
|
207
208
|
|
208
209
|
=begin
|
@@ -249,13 +250,21 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
249
250
|
test 'request should succeed if configured' do
|
250
251
|
@resource_class.case_insensitive_keys = [:email]
|
251
252
|
post :create, params: @request_params
|
253
|
+
@data = JSON.parse(response.body)
|
254
|
+
|
252
255
|
assert_equal 200, response.status
|
256
|
+
assert @data[DeviseJwtAuth.access_token_name]
|
257
|
+
assert response.cookies[DeviseJwtAuth.refresh_token_name]
|
253
258
|
end
|
254
259
|
|
255
260
|
test 'request should fail if not configured' do
|
256
261
|
@resource_class.case_insensitive_keys = []
|
257
262
|
post :create, params: @request_params
|
263
|
+
@data = JSON.parse(response.body)
|
264
|
+
|
258
265
|
assert_equal 401, response.status
|
266
|
+
assert_nil response.cookies[DeviseJwtAuth.refresh_token_name]
|
267
|
+
assert_nil @data[DeviseJwtAuth.access_token_name]
|
259
268
|
end
|
260
269
|
end
|
261
270
|
|
@@ -272,13 +281,22 @@ class DeviseJwtAuth::SessionsControllerTest < ActionController::TestCase
|
|
272
281
|
test 'request should succeed if configured' do
|
273
282
|
@resource_class.strip_whitespace_keys = [:email]
|
274
283
|
post :create, params: @request_params
|
284
|
+
@data = JSON.parse(response.body)
|
285
|
+
|
275
286
|
assert_equal 200, response.status
|
287
|
+
# p 'DATA', @data.inspect
|
288
|
+
assert @data[DeviseJwtAuth.access_token_name]
|
289
|
+
assert response.cookies[DeviseJwtAuth.refresh_token_name]
|
276
290
|
end
|
277
291
|
|
278
292
|
test 'request should fail if not configured' do
|
279
293
|
@resource_class.strip_whitespace_keys = []
|
280
294
|
post :create, params: @request_params
|
295
|
+
@data = JSON.parse(response.body)
|
296
|
+
|
281
297
|
assert_equal 401, response.status
|
298
|
+
assert_nil @data[DeviseJwtAuth.access_token_name]
|
299
|
+
assert_nil response.cookies[DeviseJwtAuth.refresh_token_name]
|
282
300
|
end
|
283
301
|
end
|
284
302
|
end
|
@@ -140,34 +140,20 @@ class DeviseJwtAuth::UnlocksControllerTest < ActionController::TestCase
|
|
140
140
|
raw_qs = response.location.split('?')[1]
|
141
141
|
@qs = Rack::Utils.parse_nested_query(raw_qs)
|
142
142
|
|
143
|
-
@access_token = @qs[
|
144
|
-
@client = @qs['client']
|
145
|
-
@client_id = @qs['client_id']
|
146
|
-
@expiry = @qs['expiry']
|
147
|
-
@token = @qs['token']
|
148
|
-
@uid = @qs['uid']
|
143
|
+
@access_token = @qs[DeviseJwtAuth.access_token_name]
|
149
144
|
@unlock = @qs['unlock']
|
145
|
+
@refresh_token = response.cookies[DeviseJwtAuth.refresh_token_name]
|
150
146
|
end
|
151
147
|
|
152
148
|
test 'respones should have success redirect status' do
|
153
149
|
assert_equal 302, response.status
|
154
150
|
end
|
155
|
-
|
151
|
+
|
156
152
|
test 'response should contain auth params' do
|
157
153
|
assert @access_token
|
158
|
-
assert @client
|
159
|
-
assert @client_id
|
160
|
-
assert @expiry
|
161
|
-
assert @token
|
162
|
-
assert @uid
|
163
154
|
assert @unlock
|
155
|
+
assert @refresh_token
|
164
156
|
end
|
165
|
-
|
166
|
-
test 'response auth params should be valid' do
|
167
|
-
assert @resource.valid_token?(@token, @client_id)
|
168
|
-
assert @resource.valid_token?(@access_token, @client)
|
169
|
-
end
|
170
|
-
=end
|
171
157
|
end
|
172
158
|
end
|
173
159
|
|
@@ -8,13 +8,13 @@ module Overrides
|
|
8
8
|
@resource = resource_class.dta_find_by(email: resource_params[:email])
|
9
9
|
|
10
10
|
if @resource && valid_params?(:email, resource_params[:email]) && @resource.valid_password?(resource_params[:password]) && @resource.confirmed?
|
11
|
-
|
11
|
+
auth_header = @resource.create_named_token_pair
|
12
12
|
@resource.save
|
13
13
|
|
14
14
|
render json: {
|
15
15
|
data: @resource.as_json(except: %i[tokens created_at updated_at]),
|
16
16
|
override_proof: OVERRIDE_PROOF
|
17
|
-
}
|
17
|
+
}.merge(auth_header)
|
18
18
|
|
19
19
|
elsif @resource && (not @resource.confirmed?)
|
20
20
|
render json: {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_jwt_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron A
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -348,10 +348,6 @@ files:
|
|
348
348
|
- test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb
|
349
349
|
- test/dummy/db/schema.rb
|
350
350
|
- test/dummy/lib/migration_database_helper.rb
|
351
|
-
- test/dummy/tmp/generators/app/models/user.rb
|
352
|
-
- test/dummy/tmp/generators/config/initializers/devise_jwt_auth.rb
|
353
|
-
- test/dummy/tmp/generators/config/routes.rb
|
354
|
-
- test/dummy/tmp/generators/db/migrate/20200206224309_devise_jwt_auth_create_users.rb
|
355
351
|
- test/factories/users.rb
|
356
352
|
- test/lib/devise_jwt_auth/blacklist_test.rb
|
357
353
|
- test/lib/devise_jwt_auth/token_factory_test.rb
|
@@ -406,10 +402,6 @@ test_files:
|
|
406
402
|
- test/test_helper.rb
|
407
403
|
- test/dummy/lib/migration_database_helper.rb
|
408
404
|
- test/dummy/config.ru
|
409
|
-
- test/dummy/tmp/generators/db/migrate/20200206224309_devise_jwt_auth_create_users.rb
|
410
|
-
- test/dummy/tmp/generators/config/routes.rb
|
411
|
-
- test/dummy/tmp/generators/config/initializers/devise_jwt_auth.rb
|
412
|
-
- test/dummy/tmp/generators/app/models/user.rb
|
413
405
|
- test/dummy/db/migrate/20140916224624_add_favorite_color_to_mangs.rb
|
414
406
|
- test/dummy/db/migrate/20140829044006_add_operating_thetan_to_user.rb
|
415
407
|
- test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb
|
@@ -1,9 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class User < ActiveRecord::Base
|
4
|
-
# Include default devise modules. Others available are:
|
5
|
-
# :confirmable, :lockable, :timeoutable and :omniauthable
|
6
|
-
devise :database_authenticatable, :registerable,
|
7
|
-
:recoverable, :rememberable, :trackable, :validatable
|
8
|
-
include DeviseJwtAuth::Concerns::User
|
9
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
DeviseJwtAuth.setup do |config|
|
4
|
-
# By default, you will only receive an access token when authenticating a
|
5
|
-
# user. To receive new access tokens, you should either reauthenticate or
|
6
|
-
# use the HTTP only refresh cookie that is sent during the authentication
|
7
|
-
# process and make refresh token requests.
|
8
|
-
# self.send_new_access_token_on_each_request = false
|
9
|
-
|
10
|
-
# By default, refresh token HTTP Only cookies last for 2 weeks. These tokens
|
11
|
-
# are used for requesting shorter-lived acccess tokens.
|
12
|
-
# self.refresh_token_lifespan = 2.weeks
|
13
|
-
|
14
|
-
# By default, access tokens last for 15 minutes. These tokens are used to
|
15
|
-
# access protected resources. When these tokens expire, you need to
|
16
|
-
# reauthenticate the user or use a refresh token cookie to get a new access
|
17
|
-
# token.
|
18
|
-
# self.access_token_lifespan = 15.minutes
|
19
|
-
|
20
|
-
# This is the name of the HTTP Only cookie that will be sent to the client
|
21
|
-
# for the purpose of requesting new access tokens.
|
22
|
-
# self.refresh_token_name = 'refresh-token'
|
23
|
-
|
24
|
-
# This is the name of the token that will be sent in the JSON responses used
|
25
|
-
# for accessing protected resources. NEVER store this token in a cookie or
|
26
|
-
# any form of local storage on the client. Save it in memory as a javascript
|
27
|
-
# variable or in some kind of context manager like Redux. Send it in your
|
28
|
-
# request headers when you want to be authenticated.
|
29
|
-
# self.access_token_name = 'access-token'
|
30
|
-
|
31
|
-
# This is the refresh token encryption key. You should set this in an
|
32
|
-
# environment variable or secret key base that isn't store in a repository.
|
33
|
-
# Also, its a good idea to NOT use the same key for access tokens.
|
34
|
-
self.refresh_token_encryption_key = 'your-refresh-token-secret-key-here'
|
35
|
-
|
36
|
-
# This is the refresh token encryption key. You should set this in an
|
37
|
-
# environment variable or secret key base that isn't store in a repository.
|
38
|
-
# Also, its a good idea to NOT use the same key for access tokens.
|
39
|
-
self.access_token_encryption_key = 'your-access-token-secret-key-here'
|
40
|
-
|
41
|
-
# This route will be the prefix for all oauth2 redirect callbacks. For
|
42
|
-
# example, using the default '/omniauth', the github oauth2 provider will
|
43
|
-
# redirect successful authentications to '/omniauth/github/callback'
|
44
|
-
# config.omniauth_prefix = "/omniauth"
|
45
|
-
|
46
|
-
# By default sending current password is not needed for the password update.
|
47
|
-
# Uncomment to enforce current_password param to be checked before all
|
48
|
-
# attribute updates. Set it to :password if you want it to be checked only if
|
49
|
-
# password is updated.
|
50
|
-
# config.check_current_password_before_update = :attributes
|
51
|
-
|
52
|
-
# By default we will use callbacks for single omniauth.
|
53
|
-
# It depends on fields like email, provider and uid.
|
54
|
-
# config.default_callbacks = true
|
55
|
-
|
56
|
-
# By default, only Bearer Token authentication is implemented out of the box.
|
57
|
-
# If, however, you wish to integrate with legacy Devise authentication, you can
|
58
|
-
# do so by enabling this flag. NOTE: This feature is highly experimental!
|
59
|
-
# config.enable_standard_devise_support = false
|
60
|
-
|
61
|
-
# By default DeviseJwtAuth will not send confirmation email, even when including
|
62
|
-
# devise confirmable module. If you want to use devise confirmable module and
|
63
|
-
# send email, set it to true. (This is a setting for compatibility)
|
64
|
-
# config.send_confirmation_email = true
|
65
|
-
|
66
|
-
# TODO: Document these settings
|
67
|
-
# self.default_confirm_success_url = nil
|
68
|
-
# self.default_password_reset_url = nil
|
69
|
-
# self.redirect_whitelist = nil
|
70
|
-
# self.update_token_version_after_password_reset = true
|
71
|
-
# self.bypass_sign_in = true
|
72
|
-
# self.require_client_password_reset_token = false
|
73
|
-
|
74
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class DeviseJwtAuthCreateUsers < ActiveRecord::Migration[6.0]
|
4
|
-
def change
|
5
|
-
|
6
|
-
create_table(:users) do |t|
|
7
|
-
## Required
|
8
|
-
t.string :provider, null: false, default: 'email'
|
9
|
-
t.string :uid, null: false, default: ''
|
10
|
-
|
11
|
-
## Database authenticatable
|
12
|
-
t.string :encrypted_password, null: false, default: ''
|
13
|
-
|
14
|
-
## Recoverable
|
15
|
-
t.string :reset_password_token
|
16
|
-
t.datetime :reset_password_sent_at
|
17
|
-
t.boolean :allow_password_change, default: false
|
18
|
-
|
19
|
-
## Rememberable
|
20
|
-
t.datetime :remember_created_at
|
21
|
-
|
22
|
-
## Confirmable
|
23
|
-
t.string :confirmation_token
|
24
|
-
t.datetime :confirmed_at
|
25
|
-
t.datetime :confirmation_sent_at
|
26
|
-
t.string :unconfirmed_email # Only if using reconfirmable
|
27
|
-
|
28
|
-
## Lockable
|
29
|
-
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
30
|
-
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
31
|
-
# t.datetime :locked_at
|
32
|
-
|
33
|
-
## User Info
|
34
|
-
t.string :name
|
35
|
-
t.string :nickname
|
36
|
-
t.string :image
|
37
|
-
t.string :email
|
38
|
-
|
39
|
-
## Tokens
|
40
|
-
t.text :tokens
|
41
|
-
|
42
|
-
t.timestamps
|
43
|
-
end
|
44
|
-
|
45
|
-
add_index :users, :email, unique: true
|
46
|
-
add_index :users, [:uid, :provider], unique: true
|
47
|
-
add_index :users, :reset_password_token, unique: true
|
48
|
-
add_index :users, :confirmation_token, unique: true
|
49
|
-
# add_index :users, :unlock_token, unique: true
|
50
|
-
end
|
51
|
-
end
|