rodauth 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +12 -0
- data/README.rdoc +5 -3
- data/doc/email_base.rdoc +1 -0
- data/doc/release_notes/1.23.0.txt +32 -0
- data/lib/rodauth.rb +5 -2
- data/lib/rodauth/features/base.rb +8 -0
- data/lib/rodauth/features/change_password_notify.rb +1 -1
- data/lib/rodauth/features/create_account.rb +1 -1
- data/lib/rodauth/features/email_auth.rb +3 -4
- data/lib/rodauth/features/email_base.rb +7 -2
- data/lib/rodauth/features/lockout.rb +1 -1
- data/lib/rodauth/features/login.rb +6 -2
- data/lib/rodauth/features/otp.rb +6 -3
- data/lib/rodauth/features/password_expiration.rb +1 -1
- data/lib/rodauth/features/recovery_codes.rb +3 -3
- data/lib/rodauth/features/reset_password.rb +2 -2
- data/lib/rodauth/features/sms_codes.rb +5 -5
- data/lib/rodauth/features/verify_account.rb +2 -2
- data/lib/rodauth/features/verify_login_change.rb +1 -1
- data/lib/rodauth/version.rb +1 -1
- data/templates/email-auth-request-form.str +2 -2
- data/templates/reset-password-request.str +3 -3
- data/templates/unlock-account-request.str +3 -3
- data/templates/verify-account-resend.str +3 -3
- metadata +5 -43
- data/Rakefile +0 -179
- data/spec/account_expiration_spec.rb +0 -225
- data/spec/all.rb +0 -1
- data/spec/change_login_spec.rb +0 -156
- data/spec/change_password_notify_spec.rb +0 -33
- data/spec/change_password_spec.rb +0 -202
- data/spec/close_account_spec.rb +0 -162
- data/spec/confirm_password_spec.rb +0 -70
- data/spec/create_account_spec.rb +0 -127
- data/spec/disallow_common_passwords_spec.rb +0 -93
- data/spec/disallow_password_reuse_spec.rb +0 -179
- data/spec/email_auth_spec.rb +0 -285
- data/spec/http_basic_auth_spec.rb +0 -143
- data/spec/jwt_cors_spec.rb +0 -57
- data/spec/jwt_refresh_spec.rb +0 -256
- data/spec/jwt_spec.rb +0 -235
- data/spec/lockout_spec.rb +0 -250
- data/spec/login_spec.rb +0 -328
- data/spec/migrate/001_tables.rb +0 -184
- data/spec/migrate/002_account_password_hash_column.rb +0 -11
- data/spec/migrate_password/001_tables.rb +0 -73
- data/spec/migrate_travis/001_tables.rb +0 -141
- data/spec/password_complexity_spec.rb +0 -109
- data/spec/password_expiration_spec.rb +0 -244
- data/spec/password_grace_period_spec.rb +0 -93
- data/spec/remember_spec.rb +0 -451
- data/spec/reset_password_spec.rb +0 -229
- data/spec/rodauth_spec.rb +0 -343
- data/spec/session_expiration_spec.rb +0 -58
- data/spec/single_session_spec.rb +0 -127
- data/spec/spec_helper.rb +0 -327
- data/spec/two_factor_spec.rb +0 -1462
- data/spec/update_password_hash_spec.rb +0 -40
- data/spec/verify_account_grace_period_spec.rb +0 -171
- data/spec/verify_account_spec.rb +0 -240
- data/spec/verify_change_login_spec.rb +0 -46
- data/spec/verify_login_change_spec.rb +0 -232
- data/spec/views/layout-other.str +0 -11
- data/spec/views/layout.str +0 -11
- data/spec/views/login.str +0 -21
@@ -1,143 +0,0 @@
|
|
1
|
-
require File.expand_path("spec_helper", File.dirname(__FILE__))
|
2
|
-
|
3
|
-
describe "Rodauth http basic auth feature" do
|
4
|
-
def basic_auth_visit(opts={})
|
5
|
-
page.driver.browser.basic_authorize(opts.fetch(:username,"foo@example.com"), opts.fetch(:password, "0123456789"))
|
6
|
-
visit(opts.fetch(:path, '/'))
|
7
|
-
end
|
8
|
-
|
9
|
-
def authorization_header(opts={})
|
10
|
-
["#{opts.delete(:username)||'foo@example.com'}:#{opts.delete(:password)||'0123456789'}"].pack("m*")
|
11
|
-
end
|
12
|
-
|
13
|
-
def basic_auth_json_request(opts={})
|
14
|
-
auth = opts.delete(:auth) || authorization_header(opts)
|
15
|
-
path = opts.delete(:path) || '/'
|
16
|
-
json_request(path, opts.merge(:headers => {"HTTP_AUTHORIZATION" => "Basic #{auth}"}, :method=>'GET'))
|
17
|
-
end
|
18
|
-
|
19
|
-
def newline_basic_auth_json_request(opts={})
|
20
|
-
auth = opts.delete(:auth) || authorization_header(opts)
|
21
|
-
auth.chomp!
|
22
|
-
basic_auth_json_request(opts.merge(:auth => auth))
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "on page visit" do
|
26
|
-
before do
|
27
|
-
rodauth do
|
28
|
-
enable :http_basic_auth
|
29
|
-
end
|
30
|
-
roda do |r|
|
31
|
-
r.rodauth
|
32
|
-
r.root{view :content=>(rodauth.logged_in? ? "Logged In" : 'Not Logged')}
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
it "handles logins" do
|
37
|
-
basic_auth_visit
|
38
|
-
page.text.must_include "Logged In"
|
39
|
-
end
|
40
|
-
|
41
|
-
it "keeps the user logged in" do
|
42
|
-
visit '/'
|
43
|
-
page.text.must_include "Not Logged"
|
44
|
-
|
45
|
-
basic_auth_visit
|
46
|
-
page.text.must_include "Logged In"
|
47
|
-
|
48
|
-
visit '/'
|
49
|
-
page.text.must_include "Logged In"
|
50
|
-
end
|
51
|
-
|
52
|
-
it "fails when no login is found" do
|
53
|
-
basic_auth_visit(:username => "foo2@example.com")
|
54
|
-
page.text.must_include "Not Logged"
|
55
|
-
page.response_headers.keys.must_include("WWW-Authenticate")
|
56
|
-
end
|
57
|
-
|
58
|
-
it "fails when passowrd does not match" do
|
59
|
-
basic_auth_visit(:password => "1111111111")
|
60
|
-
page.text.must_include "Not Logged"
|
61
|
-
page.response_headers.keys.must_include("WWW-Authenticate")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
it "requires authentication if require_http_basic_auth is true" do
|
66
|
-
rodauth do
|
67
|
-
enable :http_basic_auth
|
68
|
-
require_http_basic_auth true
|
69
|
-
end
|
70
|
-
roda do |r|
|
71
|
-
rodauth.require_authentication
|
72
|
-
r.root{view :content=>(rodauth.logged_in? ? "Logged In" : 'Not Logged')}
|
73
|
-
end
|
74
|
-
|
75
|
-
visit '/'
|
76
|
-
page.status_code.must_equal 401
|
77
|
-
page.response_headers.keys.must_include("WWW-Authenticate")
|
78
|
-
|
79
|
-
basic_auth_visit
|
80
|
-
page.text.must_include "Logged In"
|
81
|
-
end
|
82
|
-
|
83
|
-
it "works with standard authentication" do
|
84
|
-
rodauth do
|
85
|
-
enable :login, :http_basic_auth
|
86
|
-
end
|
87
|
-
roda do |r|
|
88
|
-
r.rodauth
|
89
|
-
r.root{view :content=>(rodauth.logged_in? ? "Logged In" : 'Not Logged')}
|
90
|
-
end
|
91
|
-
|
92
|
-
login
|
93
|
-
page.text.must_include "Logged In"
|
94
|
-
end
|
95
|
-
|
96
|
-
it "does not allow login to unverified account" do
|
97
|
-
rodauth do
|
98
|
-
enable :http_basic_auth
|
99
|
-
skip_status_checks? false
|
100
|
-
end
|
101
|
-
roda do |r|
|
102
|
-
r.rodauth
|
103
|
-
r.root{view :content=>(rodauth.logged_in? ? "Logged In" : 'Not Logged')}
|
104
|
-
end
|
105
|
-
DB[:accounts].update(:status_id=>1)
|
106
|
-
|
107
|
-
basic_auth_visit
|
108
|
-
page.text.must_include "Not Logged"
|
109
|
-
page.response_headers.keys.must_include("WWW-Authenticate")
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should login via jwt" do
|
113
|
-
rodauth do
|
114
|
-
enable :http_basic_auth
|
115
|
-
end
|
116
|
-
roda(:jwt) do |r|
|
117
|
-
r.rodauth
|
118
|
-
response['Content-Type'] = 'application/json'
|
119
|
-
rodauth.require_authentication
|
120
|
-
{"success"=>'You have been logged in'}
|
121
|
-
end
|
122
|
-
|
123
|
-
@authorization = nil
|
124
|
-
res = basic_auth_json_request(:auth=>'.')
|
125
|
-
res.must_equal [401, {'error'=>"Please login to continue"}]
|
126
|
-
|
127
|
-
@authorization = nil
|
128
|
-
res = basic_auth_json_request(:username=>'foo@example2.com')
|
129
|
-
res.must_equal [401, {'error'=>"Please login to continue", "field-error"=>["login", "no matching login"]}]
|
130
|
-
|
131
|
-
@authorization = nil
|
132
|
-
res = basic_auth_json_request(:password=>'012345678')
|
133
|
-
res.must_equal [401, {'error'=>"Please login to continue", "field-error"=>["password", "invalid password"]}]
|
134
|
-
|
135
|
-
@authorization = nil
|
136
|
-
res = newline_basic_auth_json_request
|
137
|
-
res.must_equal [200, {"success"=>'You have been logged in'}]
|
138
|
-
|
139
|
-
@authorization = nil
|
140
|
-
res = basic_auth_json_request
|
141
|
-
res.must_equal [200, {"success"=>'You have been logged in'}]
|
142
|
-
end
|
143
|
-
end
|
data/spec/jwt_cors_spec.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require File.expand_path("spec_helper", File.dirname(__FILE__))
|
2
|
-
|
3
|
-
describe 'Rodauth jwt_cors feature' do
|
4
|
-
it "should support CORS logins if allowed" do
|
5
|
-
origin = false
|
6
|
-
rodauth do
|
7
|
-
enable :login, :jwt_cors
|
8
|
-
jwt_secret '1'
|
9
|
-
json_response_success_key 'success'
|
10
|
-
jwt_cors_allow_origin{origin}
|
11
|
-
end
|
12
|
-
roda(:csrf=>false, :json=>true) do |r|
|
13
|
-
r.rodauth
|
14
|
-
rodauth.require_authentication
|
15
|
-
response['Content-Type'] = 'application/json'
|
16
|
-
'1'
|
17
|
-
end
|
18
|
-
|
19
|
-
# CORS Preflight Request
|
20
|
-
preflight_request = {
|
21
|
-
:method=>'OPTIONS',
|
22
|
-
:headers=>{
|
23
|
-
"HTTP_ACCESS_CONTROL_REQUEST_METHOD"=>"POST",
|
24
|
-
"HTTP_ORIGIN"=>"https://foo.example.com",
|
25
|
-
"HTTP_ACCESS_CONTROL_REQUEST_HEADERS"=>"content-type",
|
26
|
-
"CONTENT_TYPE"=>' application/json'
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
res = json_request("/login", preflight_request.dup)
|
31
|
-
res.must_equal [405, ["{\"error\":\"non-POST method used in JSON API\"}"]]
|
32
|
-
|
33
|
-
origin = Object.new
|
34
|
-
res = json_request("/login", preflight_request.dup)
|
35
|
-
res.must_equal [405, ["{\"error\":\"non-POST method used in JSON API\"}"]]
|
36
|
-
|
37
|
-
["https://foo.example.com", ["https://foo.example.com"], %r{https://foo.example.com}, true].each do |orig|
|
38
|
-
origin = orig
|
39
|
-
|
40
|
-
res = json_request("/login", preflight_request.merge(:include_headers=>true))
|
41
|
-
res[0].must_equal 204
|
42
|
-
res[1]['Access-Control-Allow-Origin'].must_equal "https://foo.example.com"
|
43
|
-
res[1]['Access-Control-Allow-Methods'].must_equal "POST"
|
44
|
-
res[1]['Access-Control-Allow-Headers'].must_equal "Content-Type, Authorization, Accept"
|
45
|
-
res[1]['Access-Control-Max-Age'].must_equal "86400"
|
46
|
-
res[2].must_equal []
|
47
|
-
|
48
|
-
res = json_request("/login", :login=>'foo@example.com', :password=>'0123456789', :headers=>{"HTTP_ORIGIN"=>"https://foo.example.com"}, :include_headers=>true)
|
49
|
-
res[0].must_equal 200
|
50
|
-
res[1]['Access-Control-Allow-Origin'].must_equal "https://foo.example.com"
|
51
|
-
res[1]['Access-Control-Expose-Headers'].must_equal "Authorization"
|
52
|
-
res[2].must_equal("success"=>"You have been logged in")
|
53
|
-
|
54
|
-
json_request("/foo").must_equal [200, 1]
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/spec/jwt_refresh_spec.rb
DELETED
@@ -1,256 +0,0 @@
|
|
1
|
-
require File.expand_path("spec_helper", File.dirname(__FILE__))
|
2
|
-
|
3
|
-
describe 'Rodauth login feature' do
|
4
|
-
it "should not have jwt refresh feature assume JWT token given during Basic/Digest authentication" do
|
5
|
-
rodauth do
|
6
|
-
enable :login, :logout, :jwt_refresh
|
7
|
-
end
|
8
|
-
roda(:jwt) do |r|
|
9
|
-
rodauth.require_authentication
|
10
|
-
'1'
|
11
|
-
end
|
12
|
-
|
13
|
-
res = json_request("/jwt-refresh", :headers=>{'HTTP_AUTHORIZATION'=>'Basic foo'})
|
14
|
-
res.must_equal [401, {'error'=>'Please login to continue'}]
|
15
|
-
|
16
|
-
res = json_request("/", :headers=>{'HTTP_AUTHORIZATION'=>'Digest foo'})
|
17
|
-
res.must_equal [401, {'error'=>'Please login to continue'}]
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should require json request content type in only json mode for rodauth endpoints only" do
|
21
|
-
oj = false
|
22
|
-
rodauth do
|
23
|
-
enable :login, :logout, :jwt_refresh
|
24
|
-
jwt_secret '1'
|
25
|
-
json_response_success_key 'success'
|
26
|
-
only_json?{oj}
|
27
|
-
end
|
28
|
-
roda(:csrf=>false, :json=>true) do |r|
|
29
|
-
r.rodauth
|
30
|
-
rodauth.require_authentication
|
31
|
-
'1'
|
32
|
-
end
|
33
|
-
|
34
|
-
res = json_request("/", :content_type=>'application/x-www-form-urlencoded', :include_headers=>true, :method=>'GET')
|
35
|
-
res[1].delete('Set-Cookie')
|
36
|
-
res.must_equal [302, {"Content-Type"=>'text/html', "Content-Length"=>'0', "Location"=>"/login",}, []]
|
37
|
-
|
38
|
-
res = json_request("/", :content_type=>'application/vnd.api+json', :method=>'GET')
|
39
|
-
res.must_equal [400, ['{"error":"Please login to continue"}']]
|
40
|
-
|
41
|
-
oj = true
|
42
|
-
|
43
|
-
res = json_request("/", :content_type=>'application/x-www-form-urlencoded', :method=>'GET')
|
44
|
-
res.must_equal [400, ['{"error":"Please login to continue"}']]
|
45
|
-
|
46
|
-
res = json_request("/", :method=>'GET')
|
47
|
-
res.must_equal [400, {'error'=>'Please login to continue'}]
|
48
|
-
|
49
|
-
res = json_request("/login", :content_type=>'application/x-www-form-urlencoded', :include_headers=>true, :method=>'GET')
|
50
|
-
msg = "Only JSON format requests are allowed"
|
51
|
-
res[1].delete('Set-Cookie')
|
52
|
-
res.must_equal [400, {"Content-Type"=>'text/html', "Content-Length"=>msg.length.to_s}, [msg]]
|
53
|
-
|
54
|
-
jwt_refresh_login
|
55
|
-
|
56
|
-
res = json_request("/", :content_type=>'application/x-www-form-urlencoded', :include_headers=>true, :method=>'GET')
|
57
|
-
# res.must_equal [200, {"Content-Type"=>'text/html', "Content-Length"=>'1'}, ['1']]
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should allow non-json requests if only_json? is false" do
|
61
|
-
rodauth do
|
62
|
-
enable :login, :logout, :jwt_refresh
|
63
|
-
jwt_secret '1'
|
64
|
-
only_json? false
|
65
|
-
end
|
66
|
-
roda(:jwt_html) do |r|
|
67
|
-
r.rodauth
|
68
|
-
rodauth.require_authentication
|
69
|
-
view(:content=>'1')
|
70
|
-
end
|
71
|
-
|
72
|
-
login
|
73
|
-
page.find('#notice_flash').text.must_equal 'You have been logged in'
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should require POST for json requests" do
|
77
|
-
rodauth do
|
78
|
-
enable :login, :logout, :jwt_refresh
|
79
|
-
jwt_secret '1'
|
80
|
-
json_response_success_key 'success'
|
81
|
-
end
|
82
|
-
roda(:jwt) do |r|
|
83
|
-
r.rodauth
|
84
|
-
end
|
85
|
-
|
86
|
-
res = json_request("/login", :method=>'GET')
|
87
|
-
res.must_equal [405, {'error'=>'non-POST method used in JSON API'}]
|
88
|
-
end
|
89
|
-
|
90
|
-
it "should require Accept contain application/json if jwt_check_accept? is true and Accept is present" do
|
91
|
-
rodauth do
|
92
|
-
enable :login, :logout, :jwt_refresh
|
93
|
-
jwt_secret '1'
|
94
|
-
json_response_success_key 'success'
|
95
|
-
jwt_check_accept? true
|
96
|
-
end
|
97
|
-
roda(:jwt) do |r|
|
98
|
-
r.rodauth
|
99
|
-
end
|
100
|
-
|
101
|
-
res = json_request("/login", :headers=>{'HTTP_ACCEPT'=>'text/html'})
|
102
|
-
res.must_equal [406, {'error'=>'Unsupported Accept header. Must accept "application/json" or compatible content type'}]
|
103
|
-
|
104
|
-
jwt_refresh_validate_login(json_request("/login", :login=>'foo@example.com', :password=>'0123456789'))
|
105
|
-
jwt_refresh_validate_login(json_request("/login", :headers=>{'HTTP_ACCEPT'=>'*/*'}, :login=>'foo@example.com', :password=>'0123456789'))
|
106
|
-
jwt_refresh_validate_login(json_request("/login", :headers=>{'HTTP_ACCEPT'=>'application/*'}, :login=>'foo@example.com', :password=>'0123456789'))
|
107
|
-
jwt_refresh_validate_login(json_request("/login", :headers=>{'HTTP_ACCEPT'=>'application/vnd.api+json'}, :login=>'foo@example.com', :password=>'0123456789'))
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should clear jwt refresh token when closing account" do
|
111
|
-
rodauth do
|
112
|
-
enable :login, :jwt_refresh, :close_account
|
113
|
-
jwt_secret '1'
|
114
|
-
end
|
115
|
-
roda(:jwt) do |r|
|
116
|
-
r.rodauth
|
117
|
-
rodauth.require_authentication
|
118
|
-
response['Content-Type'] = 'application/json'
|
119
|
-
{'hello' => 'world'}.to_json
|
120
|
-
end
|
121
|
-
|
122
|
-
jwt_refresh_login
|
123
|
-
|
124
|
-
DB[:account_jwt_refresh_keys].count.must_equal 1
|
125
|
-
res = json_request('/close-account', :password=>'0123456789')
|
126
|
-
res[1].delete('access_token').must_be_kind_of(String)
|
127
|
-
res.must_equal [200, {'success'=>"Your account has been closed"}]
|
128
|
-
DB[:account_jwt_refresh_keys].count.must_equal 0
|
129
|
-
end
|
130
|
-
|
131
|
-
|
132
|
-
it "should set refresh tokens when creating accounts when using autologin" do
|
133
|
-
rodauth do
|
134
|
-
enable :login, :create_account, :jwt_refresh
|
135
|
-
after_create_account{json_response[:account_id] = account_id}
|
136
|
-
create_account_autologin? true
|
137
|
-
end
|
138
|
-
roda(:jwt) do |r|
|
139
|
-
r.rodauth
|
140
|
-
rodauth.require_authentication
|
141
|
-
response['Content-Type'] = 'application/json'
|
142
|
-
{'hello' => 'world'}.to_json
|
143
|
-
end
|
144
|
-
|
145
|
-
res = json_request('/create-account', :login=>'foo@example2.com', "login-confirm"=>'foo@example2.com', :password=>'0123456789', "password-confirm"=>'0123456789')
|
146
|
-
refresh_token = res.last.delete('refresh_token')
|
147
|
-
@authorization = res.last.delete('access_token')
|
148
|
-
res.must_equal [200, {'success'=>"Your account has been created", 'account_id'=>DB[:accounts].max(:id)}]
|
149
|
-
|
150
|
-
res = json_request("/")
|
151
|
-
res.must_equal [200, {'hello'=>'world'}]
|
152
|
-
|
153
|
-
# We can refresh our token
|
154
|
-
res = json_request("/jwt-refresh", :refresh_token=>refresh_token)
|
155
|
-
jwt_refresh_validate(res)
|
156
|
-
@authorization = res.last.delete('access_token')
|
157
|
-
|
158
|
-
# Which we can use to access protected resources
|
159
|
-
res = json_request("/")
|
160
|
-
res.must_equal [200, {'hello'=>'world'}]
|
161
|
-
end
|
162
|
-
|
163
|
-
[false, true].each do |hs|
|
164
|
-
it "generates and refreshes Refresh Tokens #{'with hmac_secret' if hs}" do
|
165
|
-
initial_secret = secret = SecureRandom.random_bytes(32) if hs
|
166
|
-
rodauth do
|
167
|
-
enable :login, :logout, :jwt_refresh
|
168
|
-
hmac_secret{secret} if hs
|
169
|
-
jwt_secret '1'
|
170
|
-
end
|
171
|
-
roda(:jwt) do |r|
|
172
|
-
r.rodauth
|
173
|
-
rodauth.require_authentication
|
174
|
-
response['Content-Type'] = 'application/json'
|
175
|
-
{'hello' => 'world'}.to_json
|
176
|
-
end
|
177
|
-
res = json_request("/")
|
178
|
-
res.must_equal [401, {'error'=>'Please login to continue'}]
|
179
|
-
|
180
|
-
# We can login
|
181
|
-
res = jwt_refresh_login
|
182
|
-
refresh_token = res.last['refresh_token']
|
183
|
-
|
184
|
-
# Which gives us an access token which grants us access to protected resources
|
185
|
-
@authorization = res.last['access_token']
|
186
|
-
res = json_request("/")
|
187
|
-
res.must_equal [200, {'hello'=>'world'}]
|
188
|
-
|
189
|
-
# We can refresh our token
|
190
|
-
res = json_request("/jwt-refresh", :refresh_token=>refresh_token)
|
191
|
-
jwt_refresh_validate(res)
|
192
|
-
second_refresh_token = res.last['refresh_token']
|
193
|
-
|
194
|
-
# Which we can use to access protected resources
|
195
|
-
@authorization = res.last['access_token']
|
196
|
-
res = json_request("/")
|
197
|
-
res.must_equal [200, {'hello'=>'world'}]
|
198
|
-
|
199
|
-
# Subsequent refresh token is valid
|
200
|
-
res = json_request("/jwt-refresh", :refresh_token=>second_refresh_token)
|
201
|
-
jwt_refresh_validate(res)
|
202
|
-
third_refresh_token = res.last['refresh_token']
|
203
|
-
|
204
|
-
# First refresh token is now no longer valid
|
205
|
-
res = json_request("/jwt-refresh", :refresh_token=>refresh_token)
|
206
|
-
res.must_equal [400, {"error"=>"invalid JWT refresh token"}]
|
207
|
-
|
208
|
-
# Third refresh token is valid
|
209
|
-
res = json_request("/jwt-refresh", :refresh_token=>third_refresh_token)
|
210
|
-
jwt_refresh_validate(res)
|
211
|
-
fourth_refresh_token = res.last['refresh_token']
|
212
|
-
|
213
|
-
# And still gives us a valid access token
|
214
|
-
@authorization = res.last['access_token']
|
215
|
-
res = json_request("/")
|
216
|
-
res.must_equal [200, {'hello'=>'world'}]
|
217
|
-
|
218
|
-
if hs
|
219
|
-
# Refresh secret doesn't work if hmac_secret changed
|
220
|
-
secret = SecureRandom.random_bytes(32)
|
221
|
-
res = json_request("/jwt-refresh", :refresh_token=>fourth_refresh_token)
|
222
|
-
res.first.must_equal 400
|
223
|
-
res.must_equal [400, {'error'=>'invalid JWT refresh token'}]
|
224
|
-
|
225
|
-
# Refresh secret works if hmac_secret changed back
|
226
|
-
secret = initial_secret
|
227
|
-
res = json_request("/jwt-refresh", :refresh_token=>fourth_refresh_token)
|
228
|
-
jwt_refresh_validate(res)
|
229
|
-
|
230
|
-
# And still gives us a valid access token
|
231
|
-
@authorization = res.last['access_token']
|
232
|
-
res = json_request("/")
|
233
|
-
res.must_equal [200, {'hello'=>'world'}]
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
it "should not return access_token for failed login attempt" do
|
239
|
-
rodauth do
|
240
|
-
enable :login, :create_account, :jwt_refresh
|
241
|
-
after_create_account{json_response[:account_id] = account_id}
|
242
|
-
create_account_autologin? true
|
243
|
-
end
|
244
|
-
roda(:jwt) do |r|
|
245
|
-
r.rodauth
|
246
|
-
rodauth.require_authentication
|
247
|
-
response['Content-Type'] = 'application/json'
|
248
|
-
{'hello' => 'world'}.to_json
|
249
|
-
end
|
250
|
-
|
251
|
-
json_request('/create-account', :login=>'foo@example2.com', "login-confirm"=>'foo@example2.com', :password=>'0123456789', "password-confirm"=>'0123456789')
|
252
|
-
|
253
|
-
res = json_request('/login', :login=>'foo@example2.com', :password=>'123123')
|
254
|
-
res.must_equal [401, {"field-error"=>['password', 'invalid password'], "error"=>"There was an error logging in"}]
|
255
|
-
end
|
256
|
-
end
|