authpwn_rails 0.17.2 → 0.18.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/.travis.yml +1 -2
- data/Gemfile +4 -4
- data/Gemfile.lock +65 -73
- data/Gemfile.rails4 +4 -4
- data/Gemfile.rails41 +4 -4
- data/Gemfile.rails42 +4 -4
- data/VERSION +1 -1
- data/app/models/tokens/api.rb +13 -0
- data/app/models/tokens/base.rb +3 -2
- data/authpwn_rails.gemspec +22 -16
- data/lib/authpwn_rails/generators/templates/credentials.yml +4 -0
- data/lib/authpwn_rails/generators/templates/user.rb +2 -0
- data/lib/authpwn_rails/http_basic.rb +2 -2
- data/lib/authpwn_rails/http_token.rb +67 -0
- data/lib/authpwn_rails/session_controller.rb +2 -0
- data/lib/authpwn_rails/test_extensions.rb +29 -1
- data/lib/authpwn_rails/user_extensions/api_token_field.rb +30 -0
- data/lib/authpwn_rails/user_extensions/password_field.rb +0 -8
- data/lib/authpwn_rails.rb +3 -1
- data/test/credentials/api_token_test.rb +65 -0
- data/test/credentials/one_time_token_credential_test.rb +1 -1
- data/test/credentials/token_crendential_test.rb +17 -3
- data/test/helpers/routes.rb +3 -0
- data/test/http_basic_controller_test.rb +2 -2
- data/test/http_token_controller_test.rb +128 -0
- data/test/session_controller_test.rb +1 -2
- data/test/session_mailer_test.rb +0 -2
- data/test/test_helper.rb +4 -0
- data/test/user_extensions/api_token_field_test.rb +34 -0
- data/test/user_extensions/email_field_test.rb +3 -3
- data/test/user_extensions/password_field_test.rb +3 -3
- metadata +17 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 65618dde26dcdad94e8dc8e72daa2f32fd9ceef2
|
|
4
|
+
data.tar.gz: 423f8dcf94083a6e5c3ab49f6c73caa8ed6567ed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 434cb53b2466d1fa67cef7daa6b3d5a46a588568ebd82b7cef7533ac5c33e4f883b034113d8bc6a07911026e3f61d9617740e525a450aad5fb5081dd7c89bf07
|
|
7
|
+
data.tar.gz: 243f68501820c8eaecddc32d17ff36b5931ebdeacb703d0f09d696e4919ca92c687a2ea319878e155e30c2f7e63547d2aa2f394f38b73a41832e72c89f739005
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
gem 'rails', '>= 4.0.
|
|
3
|
+
gem 'rails', '>= 4.0.13'
|
|
4
4
|
|
|
5
5
|
group :development do
|
|
6
|
-
gem 'bundler', '>= 1.
|
|
6
|
+
gem 'bundler', '>= 1.6.6'
|
|
7
7
|
gem 'mocha', '>= 0.14.0'
|
|
8
8
|
gem 'jeweler', '>= 2.0.1'
|
|
9
9
|
gem 'simplecov', '>= 0'
|
|
10
|
-
gem 'mysql2', '>= 0.3.
|
|
10
|
+
gem 'mysql2', '>= 0.3.18'
|
|
11
11
|
gem 'omniauth', '>= 1.2.2'
|
|
12
|
-
gem 'pg', '>= 0.
|
|
12
|
+
gem 'pg', '>= 0.18.2'
|
|
13
13
|
gem 'sqlite3', '>= 1.3.9'
|
|
14
14
|
gem 'rubysl', platforms: [:rbx]
|
|
15
15
|
gem 'rubysl-bundler', platforms: [:rbx]
|
data/Gemfile.lock
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
GEM
|
|
2
2
|
remote: https://rubygems.org/
|
|
3
3
|
specs:
|
|
4
|
-
actionmailer (4.2.
|
|
5
|
-
actionpack (= 4.2.
|
|
6
|
-
actionview (= 4.2.
|
|
7
|
-
activejob (= 4.2.
|
|
4
|
+
actionmailer (4.2.2)
|
|
5
|
+
actionpack (= 4.2.2)
|
|
6
|
+
actionview (= 4.2.2)
|
|
7
|
+
activejob (= 4.2.2)
|
|
8
8
|
mail (~> 2.5, >= 2.5.4)
|
|
9
9
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
|
10
|
-
actionpack (4.2.
|
|
11
|
-
actionview (= 4.2.
|
|
12
|
-
activesupport (= 4.2.
|
|
13
|
-
rack (~> 1.6
|
|
10
|
+
actionpack (4.2.2)
|
|
11
|
+
actionview (= 4.2.2)
|
|
12
|
+
activesupport (= 4.2.2)
|
|
13
|
+
rack (~> 1.6)
|
|
14
14
|
rack-test (~> 0.6.2)
|
|
15
15
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
|
16
16
|
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
|
17
|
-
actionview (4.2.
|
|
18
|
-
activesupport (= 4.2.
|
|
17
|
+
actionview (4.2.2)
|
|
18
|
+
activesupport (= 4.2.2)
|
|
19
19
|
builder (~> 3.1)
|
|
20
20
|
erubis (~> 2.7.0)
|
|
21
21
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
|
22
22
|
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
|
23
|
-
activejob (4.2.
|
|
24
|
-
activesupport (= 4.2.
|
|
23
|
+
activejob (4.2.2)
|
|
24
|
+
activesupport (= 4.2.2)
|
|
25
25
|
globalid (>= 0.3.0)
|
|
26
|
-
activemodel (4.2.
|
|
27
|
-
activesupport (= 4.2.
|
|
26
|
+
activemodel (4.2.2)
|
|
27
|
+
activesupport (= 4.2.2)
|
|
28
28
|
builder (~> 3.1)
|
|
29
|
-
activerecord (4.2.
|
|
30
|
-
activemodel (= 4.2.
|
|
31
|
-
activesupport (= 4.2.
|
|
29
|
+
activerecord (4.2.2)
|
|
30
|
+
activemodel (= 4.2.2)
|
|
31
|
+
activesupport (= 4.2.2)
|
|
32
32
|
arel (~> 6.0)
|
|
33
|
-
activesupport (4.2.
|
|
33
|
+
activesupport (4.2.2)
|
|
34
34
|
i18n (~> 0.7)
|
|
35
35
|
json (~> 1.7, >= 1.7.7)
|
|
36
36
|
minitest (~> 5.1)
|
|
37
37
|
thread_safe (~> 0.3, >= 0.3.4)
|
|
38
38
|
tzinfo (~> 1.1)
|
|
39
|
-
addressable (2.3.
|
|
39
|
+
addressable (2.3.8)
|
|
40
40
|
arel (6.0.0)
|
|
41
41
|
builder (3.2.2)
|
|
42
42
|
descendants_tracker (0.0.4)
|
|
@@ -46,8 +46,8 @@ GEM
|
|
|
46
46
|
faraday (0.9.1)
|
|
47
47
|
multipart-post (>= 1.2, < 3)
|
|
48
48
|
ffi2-generators (0.1.1)
|
|
49
|
-
git (1.2.
|
|
50
|
-
github_api (0.12.
|
|
49
|
+
git (1.2.9.1)
|
|
50
|
+
github_api (0.12.3)
|
|
51
51
|
addressable (~> 2.3)
|
|
52
52
|
descendants_tracker (~> 0.0.4)
|
|
53
53
|
faraday (~> 0.8, < 0.10)
|
|
@@ -55,11 +55,10 @@ GEM
|
|
|
55
55
|
multi_json (>= 1.7.5, < 2.0)
|
|
56
56
|
nokogiri (~> 1.6.3)
|
|
57
57
|
oauth2
|
|
58
|
-
globalid (0.3.
|
|
58
|
+
globalid (0.3.5)
|
|
59
59
|
activesupport (>= 4.1.0)
|
|
60
|
-
hashie (3.
|
|
61
|
-
highline (1.
|
|
62
|
-
hike (1.2.3)
|
|
60
|
+
hashie (3.4.2)
|
|
61
|
+
highline (1.7.2)
|
|
63
62
|
i18n (0.7.0)
|
|
64
63
|
jeweler (2.0.1)
|
|
65
64
|
builder
|
|
@@ -70,23 +69,23 @@ GEM
|
|
|
70
69
|
nokogiri (>= 1.5.10)
|
|
71
70
|
rake
|
|
72
71
|
rdoc
|
|
73
|
-
json (1.8.
|
|
74
|
-
jwt (1.
|
|
75
|
-
loofah (2.0.
|
|
72
|
+
json (1.8.3)
|
|
73
|
+
jwt (1.5.0)
|
|
74
|
+
loofah (2.0.2)
|
|
76
75
|
nokogiri (>= 1.5.9)
|
|
77
76
|
mail (2.6.3)
|
|
78
77
|
mime-types (>= 1.16, < 3)
|
|
79
78
|
metaclass (0.0.4)
|
|
80
|
-
mime-types (2.
|
|
79
|
+
mime-types (2.6.1)
|
|
81
80
|
mini_portile (0.6.2)
|
|
82
|
-
minitest (5.
|
|
81
|
+
minitest (5.7.0)
|
|
83
82
|
mocha (1.1.0)
|
|
84
83
|
metaclass (~> 0.0.1)
|
|
85
|
-
multi_json (1.
|
|
84
|
+
multi_json (1.11.1)
|
|
86
85
|
multi_xml (0.5.5)
|
|
87
86
|
multipart-post (2.0.0)
|
|
88
|
-
mysql2 (0.3.
|
|
89
|
-
nokogiri (1.6.
|
|
87
|
+
mysql2 (0.3.18)
|
|
88
|
+
nokogiri (1.6.6.2)
|
|
90
89
|
mini_portile (~> 0.6.0)
|
|
91
90
|
oauth2 (1.0.0)
|
|
92
91
|
faraday (>= 0.8, < 0.10)
|
|
@@ -97,38 +96,36 @@ GEM
|
|
|
97
96
|
omniauth (1.2.2)
|
|
98
97
|
hashie (>= 1.2, < 4)
|
|
99
98
|
rack (~> 1.0)
|
|
100
|
-
pg (0.18.
|
|
101
|
-
rack (1.6.
|
|
99
|
+
pg (0.18.2)
|
|
100
|
+
rack (1.6.2)
|
|
102
101
|
rack-test (0.6.3)
|
|
103
102
|
rack (>= 1.0)
|
|
104
|
-
rails (4.2.
|
|
105
|
-
actionmailer (= 4.2.
|
|
106
|
-
actionpack (= 4.2.
|
|
107
|
-
actionview (= 4.2.
|
|
108
|
-
activejob (= 4.2.
|
|
109
|
-
activemodel (= 4.2.
|
|
110
|
-
activerecord (= 4.2.
|
|
111
|
-
activesupport (= 4.2.
|
|
103
|
+
rails (4.2.2)
|
|
104
|
+
actionmailer (= 4.2.2)
|
|
105
|
+
actionpack (= 4.2.2)
|
|
106
|
+
actionview (= 4.2.2)
|
|
107
|
+
activejob (= 4.2.2)
|
|
108
|
+
activemodel (= 4.2.2)
|
|
109
|
+
activerecord (= 4.2.2)
|
|
110
|
+
activesupport (= 4.2.2)
|
|
112
111
|
bundler (>= 1.3.0, < 2.0)
|
|
113
|
-
railties (= 4.2.
|
|
112
|
+
railties (= 4.2.2)
|
|
114
113
|
sprockets-rails
|
|
115
114
|
rails-deprecated_sanitizer (1.0.3)
|
|
116
115
|
activesupport (>= 4.2.0.alpha)
|
|
117
|
-
rails-dom-testing (1.0.
|
|
116
|
+
rails-dom-testing (1.0.6)
|
|
118
117
|
activesupport (>= 4.2.0.beta, < 5.0)
|
|
119
118
|
nokogiri (~> 1.6.0)
|
|
120
119
|
rails-deprecated_sanitizer (>= 1.0.1)
|
|
121
|
-
rails-html-sanitizer (1.0.
|
|
120
|
+
rails-html-sanitizer (1.0.2)
|
|
122
121
|
loofah (~> 2.0)
|
|
123
|
-
railties (4.2.
|
|
124
|
-
actionpack (= 4.2.
|
|
125
|
-
activesupport (= 4.2.
|
|
122
|
+
railties (4.2.2)
|
|
123
|
+
actionpack (= 4.2.2)
|
|
124
|
+
activesupport (= 4.2.2)
|
|
126
125
|
rake (>= 0.8.7)
|
|
127
126
|
thor (>= 0.18.1, < 2.0)
|
|
128
127
|
rake (10.4.2)
|
|
129
|
-
rb-readline (0.5.2)
|
|
130
128
|
rdoc (4.2.0)
|
|
131
|
-
json (~> 1.4)
|
|
132
129
|
rubysl (2.1.0)
|
|
133
130
|
rubysl-abbrev (~> 2.0)
|
|
134
131
|
rubysl-base64 (~> 2.0)
|
|
@@ -242,9 +239,9 @@ GEM
|
|
|
242
239
|
rubysl-csv (2.0.2)
|
|
243
240
|
rubysl-english (~> 2.0)
|
|
244
241
|
rubysl-curses (2.0.1)
|
|
245
|
-
rubysl-date (2.0.
|
|
242
|
+
rubysl-date (2.0.9)
|
|
246
243
|
rubysl-delegate (2.0.1)
|
|
247
|
-
rubysl-digest (2.0.
|
|
244
|
+
rubysl-digest (2.0.8)
|
|
248
245
|
rubysl-drb (2.0.1)
|
|
249
246
|
rubysl-e2mmap (2.0.0)
|
|
250
247
|
rubysl-english (2.0.0)
|
|
@@ -267,8 +264,7 @@ GEM
|
|
|
267
264
|
rubysl-io-nonblock (2.0.0)
|
|
268
265
|
rubysl-io-wait (2.0.0)
|
|
269
266
|
rubysl-ipaddr (2.0.0)
|
|
270
|
-
rubysl-irb (2.1.
|
|
271
|
-
rb-readline (~> 0.5)
|
|
267
|
+
rubysl-irb (2.1.1)
|
|
272
268
|
rubysl-e2mmap (~> 2.0)
|
|
273
269
|
rubysl-mathn (~> 2.0)
|
|
274
270
|
rubysl-thread (~> 2.0)
|
|
@@ -295,7 +291,7 @@ GEM
|
|
|
295
291
|
rubysl-observer (2.0.0)
|
|
296
292
|
rubysl-open-uri (2.0.0)
|
|
297
293
|
rubysl-open3 (2.0.0)
|
|
298
|
-
rubysl-openssl (2.
|
|
294
|
+
rubysl-openssl (2.3.0)
|
|
299
295
|
rubysl-optparse (2.0.1)
|
|
300
296
|
rubysl-shellwords (~> 2.0)
|
|
301
297
|
rubysl-ostruct (2.0.4)
|
|
@@ -320,7 +316,7 @@ GEM
|
|
|
320
316
|
rubysl-tempfile (~> 2.0)
|
|
321
317
|
rubysl-thread (~> 2.0)
|
|
322
318
|
rubysl-rational (2.0.1)
|
|
323
|
-
rubysl-resolv (2.1.
|
|
319
|
+
rubysl-resolv (2.1.2)
|
|
324
320
|
rubysl-rexml (2.0.4)
|
|
325
321
|
rubysl-rinda (2.0.1)
|
|
326
322
|
rubysl-rss (2.0.0)
|
|
@@ -336,7 +332,7 @@ GEM
|
|
|
336
332
|
rubysl-syslog (2.1.0)
|
|
337
333
|
ffi2-generators (~> 0.1)
|
|
338
334
|
rubysl-tempfile (2.0.1)
|
|
339
|
-
rubysl-thread (2.0.
|
|
335
|
+
rubysl-thread (2.0.3)
|
|
340
336
|
rubysl-thwait (2.0.0)
|
|
341
337
|
rubysl-time (2.0.3)
|
|
342
338
|
rubysl-timeout (2.0.0)
|
|
@@ -351,24 +347,20 @@ GEM
|
|
|
351
347
|
rubysl-xmlrpc (2.0.0)
|
|
352
348
|
rubysl-yaml (2.1.0)
|
|
353
349
|
rubysl-zlib (2.0.1)
|
|
354
|
-
simplecov (0.
|
|
350
|
+
simplecov (0.10.0)
|
|
355
351
|
docile (~> 1.1.0)
|
|
356
|
-
|
|
357
|
-
simplecov-html (~> 0.
|
|
358
|
-
simplecov-html (0.
|
|
359
|
-
sprockets (2.
|
|
360
|
-
hike (~> 1.2)
|
|
361
|
-
multi_json (~> 1.0)
|
|
352
|
+
json (~> 1.8)
|
|
353
|
+
simplecov-html (~> 0.10.0)
|
|
354
|
+
simplecov-html (0.10.0)
|
|
355
|
+
sprockets (3.2.0)
|
|
362
356
|
rack (~> 1.0)
|
|
363
|
-
|
|
364
|
-
sprockets-rails (2.2.2)
|
|
357
|
+
sprockets-rails (2.3.1)
|
|
365
358
|
actionpack (>= 3.0)
|
|
366
359
|
activesupport (>= 3.0)
|
|
367
360
|
sprockets (>= 2.8, < 4.0)
|
|
368
361
|
sqlite3 (1.3.10)
|
|
369
362
|
thor (0.19.1)
|
|
370
|
-
thread_safe (0.3.
|
|
371
|
-
tilt (1.4.1)
|
|
363
|
+
thread_safe (0.3.5)
|
|
372
364
|
tzinfo (1.2.2)
|
|
373
365
|
thread_safe (~> 0.1)
|
|
374
366
|
|
|
@@ -376,13 +368,13 @@ PLATFORMS
|
|
|
376
368
|
ruby
|
|
377
369
|
|
|
378
370
|
DEPENDENCIES
|
|
379
|
-
bundler (>= 1.
|
|
371
|
+
bundler (>= 1.6.6)
|
|
380
372
|
jeweler (>= 2.0.1)
|
|
381
373
|
mocha (>= 0.14.0)
|
|
382
|
-
mysql2 (>= 0.3.
|
|
374
|
+
mysql2 (>= 0.3.18)
|
|
383
375
|
omniauth (>= 1.2.2)
|
|
384
|
-
pg (>= 0.
|
|
385
|
-
rails (>= 4.0.
|
|
376
|
+
pg (>= 0.18.2)
|
|
377
|
+
rails (>= 4.0.13)
|
|
386
378
|
rubysl
|
|
387
379
|
rubysl-bundler
|
|
388
380
|
rubysl-rake
|
data/Gemfile.rails4
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
gem 'rails', '~> 4.0.
|
|
3
|
+
gem 'rails', '~> 4.0.13'
|
|
4
4
|
|
|
5
5
|
group :development do
|
|
6
|
-
gem 'bundler', '>= 1.6.
|
|
6
|
+
gem 'bundler', '>= 1.6.6'
|
|
7
7
|
gem 'mocha', '>= 1.1.0'
|
|
8
8
|
gem 'jeweler', '>= 2.0.1'
|
|
9
9
|
gem 'simplecov', '>= 0'
|
|
10
|
-
gem 'mysql2', '>= 0.3.
|
|
10
|
+
gem 'mysql2', '>= 0.3.18'
|
|
11
11
|
gem 'omniauth', '>= 1.2.2'
|
|
12
|
-
gem 'pg', '>= 0.
|
|
12
|
+
gem 'pg', '>= 0.18.2'
|
|
13
13
|
gem 'sqlite3', '>= 1.3.10'
|
|
14
14
|
gem 'rubysl', platforms: [:rbx]
|
|
15
15
|
gem 'rubysl-bundler', platforms: [:rbx]
|
data/Gemfile.rails41
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
gem 'rails', '~> 4.1.
|
|
3
|
+
gem 'rails', '~> 4.1.10'
|
|
4
4
|
|
|
5
5
|
group :development do
|
|
6
|
-
gem 'bundler', '>= 1.6.
|
|
6
|
+
gem 'bundler', '>= 1.6.6'
|
|
7
7
|
gem 'mocha', '>= 1.1.0'
|
|
8
8
|
gem 'jeweler', '>= 2.0.1'
|
|
9
9
|
gem 'simplecov', '>= 0'
|
|
10
|
-
gem 'mysql2', '>= 0.3.
|
|
10
|
+
gem 'mysql2', '>= 0.3.18'
|
|
11
11
|
gem 'omniauth', '>= 1.2.2'
|
|
12
|
-
gem 'pg', '>= 0.
|
|
12
|
+
gem 'pg', '>= 0.18.2'
|
|
13
13
|
gem 'sqlite3', '>= 1.3.10'
|
|
14
14
|
gem 'rubysl', platforms: [:rbx]
|
|
15
15
|
gem 'rubysl-bundler', platforms: [:rbx]
|
data/Gemfile.rails42
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
gem 'rails', '
|
|
3
|
+
gem 'rails', '~> 4.2.2'
|
|
4
4
|
|
|
5
5
|
group :development do
|
|
6
|
-
gem 'bundler', '>= 1.6.
|
|
6
|
+
gem 'bundler', '>= 1.6.6'
|
|
7
7
|
gem 'mocha', '>= 1.1.0'
|
|
8
8
|
gem 'jeweler', '>= 2.0.1'
|
|
9
9
|
gem 'simplecov', '>= 0'
|
|
10
|
-
gem 'mysql2', '>= 0.3.
|
|
10
|
+
gem 'mysql2', '>= 0.3.18'
|
|
11
11
|
gem 'omniauth', '>= 1.2.2'
|
|
12
|
-
gem 'pg', '>= 0.
|
|
12
|
+
gem 'pg', '>= 0.18.2'
|
|
13
13
|
gem 'sqlite3', '>= 1.3.10'
|
|
14
14
|
gem 'rubysl', platforms: [:rbx]
|
|
15
15
|
gem 'rubysl-bundler', platforms: [:rbx]
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.18.0
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# :namespace
|
|
2
|
+
module Tokens
|
|
3
|
+
|
|
4
|
+
# API tokens can be used to issue API calls on behalf of an account.
|
|
5
|
+
class Api < Tokens::Base
|
|
6
|
+
# NOTE: If we ever implement OAuth tokens, they should hang off of API
|
|
7
|
+
# tokens.
|
|
8
|
+
|
|
9
|
+
# For now, we allow exactly one API token for each user.
|
|
10
|
+
validates :user, uniqueness: { scope: :type }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end # namespace Tokens
|
data/app/models/tokens/base.rb
CHANGED
|
@@ -27,8 +27,9 @@ class Base < ::Credential
|
|
|
27
27
|
# Returns the authenticated User instance, or a symbol indicating the reason
|
|
28
28
|
# why the (potentially valid) token code was rejected.
|
|
29
29
|
def self.authenticate(code)
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
return :invalid unless token = self.with_code(code).first
|
|
31
|
+
return :invalid unless token.kind_of?(self)
|
|
32
|
+
token.authenticate
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
# Scope that uses a secret code.
|
data/authpwn_rails.gemspec
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: authpwn_rails 0.
|
|
5
|
+
# stub: authpwn_rails 0.18.0 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "authpwn_rails"
|
|
9
|
-
s.version = "0.
|
|
9
|
+
s.version = "0.18.0"
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["lib"]
|
|
13
13
|
s.authors = ["Victor Costan"]
|
|
14
|
-
s.date = "2015-
|
|
14
|
+
s.date = "2015-06-17"
|
|
15
15
|
s.description = "Works with Facebook."
|
|
16
16
|
s.email = "victor@costan.us"
|
|
17
17
|
s.extra_rdoc_files = [
|
|
@@ -35,6 +35,7 @@ Gem::Specification.new do |s|
|
|
|
35
35
|
"app/models/credentials/email.rb",
|
|
36
36
|
"app/models/credentials/omni_auth_uid.rb",
|
|
37
37
|
"app/models/credentials/password.rb",
|
|
38
|
+
"app/models/tokens/api.rb",
|
|
38
39
|
"app/models/tokens/base.rb",
|
|
39
40
|
"app/models/tokens/email_verification.rb",
|
|
40
41
|
"app/models/tokens/one_time.rb",
|
|
@@ -72,16 +73,19 @@ Gem::Specification.new do |s|
|
|
|
72
73
|
"lib/authpwn_rails/generators/templates/user.rb",
|
|
73
74
|
"lib/authpwn_rails/generators/templates/users.yml",
|
|
74
75
|
"lib/authpwn_rails/http_basic.rb",
|
|
76
|
+
"lib/authpwn_rails/http_token.rb",
|
|
75
77
|
"lib/authpwn_rails/routes.rb",
|
|
76
78
|
"lib/authpwn_rails/session.rb",
|
|
77
79
|
"lib/authpwn_rails/session_controller.rb",
|
|
78
80
|
"lib/authpwn_rails/session_mailer.rb",
|
|
79
81
|
"lib/authpwn_rails/session_model.rb",
|
|
80
82
|
"lib/authpwn_rails/test_extensions.rb",
|
|
83
|
+
"lib/authpwn_rails/user_extensions/api_token_field.rb",
|
|
81
84
|
"lib/authpwn_rails/user_extensions/email_field.rb",
|
|
82
85
|
"lib/authpwn_rails/user_extensions/password_field.rb",
|
|
83
86
|
"lib/authpwn_rails/user_model.rb",
|
|
84
87
|
"test/cookie_controller_test.rb",
|
|
88
|
+
"test/credentials/api_token_test.rb",
|
|
85
89
|
"test/credentials/email_credential_test.rb",
|
|
86
90
|
"test/credentials/email_verification_token_test.rb",
|
|
87
91
|
"test/credentials/omni_auth_uid_credential_test.rb",
|
|
@@ -108,6 +112,7 @@ Gem::Specification.new do |s|
|
|
|
108
112
|
"test/helpers/test_order.rb",
|
|
109
113
|
"test/helpers/view_helpers.rb",
|
|
110
114
|
"test/http_basic_controller_test.rb",
|
|
115
|
+
"test/http_token_controller_test.rb",
|
|
111
116
|
"test/initializer_test.rb",
|
|
112
117
|
"test/routes_test.rb",
|
|
113
118
|
"test/session_controller_api_test.rb",
|
|
@@ -117,54 +122,55 @@ Gem::Specification.new do |s|
|
|
|
117
122
|
"test/session_test.rb",
|
|
118
123
|
"test/test_extensions_test.rb",
|
|
119
124
|
"test/test_helper.rb",
|
|
125
|
+
"test/user_extensions/api_token_field_test.rb",
|
|
120
126
|
"test/user_extensions/email_field_test.rb",
|
|
121
127
|
"test/user_extensions/password_field_test.rb",
|
|
122
128
|
"test/user_test.rb"
|
|
123
129
|
]
|
|
124
130
|
s.homepage = "http://github.com/pwnall/authpwn_rails"
|
|
125
131
|
s.licenses = ["MIT"]
|
|
126
|
-
s.rubygems_version = "2.
|
|
132
|
+
s.rubygems_version = "2.4.6"
|
|
127
133
|
s.summary = "User authentication for Rails 4 applications."
|
|
128
134
|
|
|
129
135
|
if s.respond_to? :specification_version then
|
|
130
136
|
s.specification_version = 4
|
|
131
137
|
|
|
132
138
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
133
|
-
s.add_runtime_dependency(%q<rails>, [">= 4.0.
|
|
134
|
-
s.add_development_dependency(%q<bundler>, [">= 1.
|
|
139
|
+
s.add_runtime_dependency(%q<rails>, [">= 4.0.13"])
|
|
140
|
+
s.add_development_dependency(%q<bundler>, [">= 1.6.6"])
|
|
135
141
|
s.add_development_dependency(%q<mocha>, [">= 0.14.0"])
|
|
136
142
|
s.add_development_dependency(%q<jeweler>, [">= 2.0.1"])
|
|
137
143
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
|
138
|
-
s.add_development_dependency(%q<mysql2>, [">= 0.3.
|
|
144
|
+
s.add_development_dependency(%q<mysql2>, [">= 0.3.18"])
|
|
139
145
|
s.add_development_dependency(%q<omniauth>, [">= 1.2.2"])
|
|
140
|
-
s.add_development_dependency(%q<pg>, [">= 0.
|
|
146
|
+
s.add_development_dependency(%q<pg>, [">= 0.18.2"])
|
|
141
147
|
s.add_development_dependency(%q<sqlite3>, [">= 1.3.9"])
|
|
142
148
|
s.add_development_dependency(%q<rubysl>, [">= 0"])
|
|
143
149
|
s.add_development_dependency(%q<rubysl-bundler>, [">= 0"])
|
|
144
150
|
s.add_development_dependency(%q<rubysl-rake>, [">= 0"])
|
|
145
151
|
else
|
|
146
|
-
s.add_dependency(%q<rails>, [">= 4.0.
|
|
147
|
-
s.add_dependency(%q<bundler>, [">= 1.
|
|
152
|
+
s.add_dependency(%q<rails>, [">= 4.0.13"])
|
|
153
|
+
s.add_dependency(%q<bundler>, [">= 1.6.6"])
|
|
148
154
|
s.add_dependency(%q<mocha>, [">= 0.14.0"])
|
|
149
155
|
s.add_dependency(%q<jeweler>, [">= 2.0.1"])
|
|
150
156
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
|
151
|
-
s.add_dependency(%q<mysql2>, [">= 0.3.
|
|
157
|
+
s.add_dependency(%q<mysql2>, [">= 0.3.18"])
|
|
152
158
|
s.add_dependency(%q<omniauth>, [">= 1.2.2"])
|
|
153
|
-
s.add_dependency(%q<pg>, [">= 0.
|
|
159
|
+
s.add_dependency(%q<pg>, [">= 0.18.2"])
|
|
154
160
|
s.add_dependency(%q<sqlite3>, [">= 1.3.9"])
|
|
155
161
|
s.add_dependency(%q<rubysl>, [">= 0"])
|
|
156
162
|
s.add_dependency(%q<rubysl-bundler>, [">= 0"])
|
|
157
163
|
s.add_dependency(%q<rubysl-rake>, [">= 0"])
|
|
158
164
|
end
|
|
159
165
|
else
|
|
160
|
-
s.add_dependency(%q<rails>, [">= 4.0.
|
|
161
|
-
s.add_dependency(%q<bundler>, [">= 1.
|
|
166
|
+
s.add_dependency(%q<rails>, [">= 4.0.13"])
|
|
167
|
+
s.add_dependency(%q<bundler>, [">= 1.6.6"])
|
|
162
168
|
s.add_dependency(%q<mocha>, [">= 0.14.0"])
|
|
163
169
|
s.add_dependency(%q<jeweler>, [">= 2.0.1"])
|
|
164
170
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
|
165
|
-
s.add_dependency(%q<mysql2>, [">= 0.3.
|
|
171
|
+
s.add_dependency(%q<mysql2>, [">= 0.3.18"])
|
|
166
172
|
s.add_dependency(%q<omniauth>, [">= 1.2.2"])
|
|
167
|
-
s.add_dependency(%q<pg>, [">= 0.
|
|
173
|
+
s.add_dependency(%q<pg>, [">= 0.18.2"])
|
|
168
174
|
s.add_dependency(%q<sqlite3>, [">= 1.3.9"])
|
|
169
175
|
s.add_dependency(%q<rubysl>, [">= 0"])
|
|
170
176
|
s.add_dependency(%q<rubysl-bundler>, [">= 0"])
|
|
@@ -6,6 +6,8 @@ class User < ActiveRecord::Base
|
|
|
6
6
|
# include Authpwn::UserExtensions::EmailField
|
|
7
7
|
# Virtual password attribute, with confirmation validation.
|
|
8
8
|
# include Authpwn::UserExtensions::PasswordField
|
|
9
|
+
# Virtual API token attribute.
|
|
10
|
+
# include Authpwn::UserExtensions::ApiTokenField
|
|
9
11
|
|
|
10
12
|
# Change this to customize user lookup in the e-mail/password signin process.
|
|
11
13
|
#
|
|
@@ -5,8 +5,8 @@ class ActionController::Base
|
|
|
5
5
|
# Keeps track of the currently authenticated user via the session.
|
|
6
6
|
#
|
|
7
7
|
# Assumes the existence of a User model. A bare ActiveModel model will do the
|
|
8
|
-
# trick. Model instances must implement id, and the model class must
|
|
9
|
-
# find_by_id.
|
|
8
|
+
# trick. Model instances must implement id, and the model class must
|
|
9
|
+
# implement find_by_id.
|
|
10
10
|
def self.authenticates_using_http_basic(options = {})
|
|
11
11
|
include Authpwn::HttpBasicControllerInstanceMethods
|
|
12
12
|
before_filter :authenticate_using_http_basic, options
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'action_controller'
|
|
2
|
+
|
|
3
|
+
# :nodoc: adds authenticates_using_http_token
|
|
4
|
+
class ActionController::Base
|
|
5
|
+
# Keeps track of the currently authenticated user via the session.
|
|
6
|
+
#
|
|
7
|
+
# Assumes the existence of a User model. A bare ActiveModel model will do the
|
|
8
|
+
# trick. Model instances must implement id, and the model class must implement
|
|
9
|
+
# find_by_id.
|
|
10
|
+
def self.authenticates_using_http_token(options = {})
|
|
11
|
+
include Authpwn::HttpTokenControllerInstanceMethods
|
|
12
|
+
before_action :authenticate_using_http_token, options
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# :nodoc: namespace
|
|
17
|
+
module Authpwn
|
|
18
|
+
|
|
19
|
+
# Included in controllers that call authenticates_using_http_token.
|
|
20
|
+
module HttpTokenControllerInstanceMethods
|
|
21
|
+
include Authpwn::CurrentUser
|
|
22
|
+
|
|
23
|
+
# The before_action that implements authenticates_using_http_token.
|
|
24
|
+
#
|
|
25
|
+
# If your ApplicationController contains authenticates_using_http_token, you
|
|
26
|
+
# can opt out in individual controllers using skip_before_action.
|
|
27
|
+
#
|
|
28
|
+
# skip_before_action :authenticate_using_http_filter
|
|
29
|
+
def authenticate_using_http_token
|
|
30
|
+
return if current_user
|
|
31
|
+
authenticate_with_http_token do |token_code, options|
|
|
32
|
+
auth = Tokens::Api.authenticate token_code
|
|
33
|
+
|
|
34
|
+
# NOTE: Setting the instance variable directly bypasses the session
|
|
35
|
+
# setup. Tokens are generally used in API contexts, so the session
|
|
36
|
+
# cookie would get ignored anyway.
|
|
37
|
+
@current_user = auth unless auth.kind_of? Symbol
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
private :authenticate_using_http_token
|
|
41
|
+
|
|
42
|
+
# Inform the user that their request is forbidden.
|
|
43
|
+
#
|
|
44
|
+
# If a user is logged on, this renders the session/forbidden view with a HTTP
|
|
45
|
+
# 403 code.
|
|
46
|
+
#
|
|
47
|
+
# If no user is logged in, a HTTP 403 code is returned, together with an
|
|
48
|
+
# HTTP Authentication header causing the user-agent (browser) to initiate
|
|
49
|
+
# http token authentication.
|
|
50
|
+
def bounce_to_http_token()
|
|
51
|
+
unless current_user
|
|
52
|
+
request_http_token_authentication
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
respond_to do |format|
|
|
57
|
+
format.html do
|
|
58
|
+
render 'session/forbidden', status: :forbidden
|
|
59
|
+
end
|
|
60
|
+
format.json do
|
|
61
|
+
render json: { error: "You're not allowed to access that" }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end # module Authpwn::HttpTokenControllerInstanceMethods
|
|
66
|
+
|
|
67
|
+
end # namespace Authpwn
|
|
@@ -127,6 +127,8 @@ module SessionController
|
|
|
127
127
|
|
|
128
128
|
# GET /session/token/token-code
|
|
129
129
|
def token
|
|
130
|
+
# NOTE: This repeats the code in Token::Base.authenticate, because we need
|
|
131
|
+
# the token.
|
|
130
132
|
if token = Tokens::Base.with_code(params[:code]).first
|
|
131
133
|
auth = token.authenticate
|
|
132
134
|
else
|
|
@@ -59,7 +59,7 @@ module ControllerTestExtensions
|
|
|
59
59
|
Tokens::Base.with_code(suid).first!.user
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
# Sets the HTTP Authentication header.
|
|
62
|
+
# Sets the HTTP Authentication header for Basic authentication.
|
|
63
63
|
#
|
|
64
64
|
# If no password is provided, the user's password is set to "password". This
|
|
65
65
|
# change is normally reverted at the end of the test, as long as
|
|
@@ -95,6 +95,34 @@ module ControllerTestExtensions
|
|
|
95
95
|
"Basic #{::Base64.strict_encode64("#{email}:#{password}")}"
|
|
96
96
|
self
|
|
97
97
|
end
|
|
98
|
+
|
|
99
|
+
# Sets the HTTP Authentication header for Token authentication.
|
|
100
|
+
#
|
|
101
|
+
# If the user doesn't have an API token, one is generated automatically. This
|
|
102
|
+
# change is normally reverted at the end of the test, as long as
|
|
103
|
+
# transactional fixtures are not disabled.
|
|
104
|
+
#
|
|
105
|
+
# If a token code is provided, the user's API token's code is forced to the
|
|
106
|
+
# given value.
|
|
107
|
+
#
|
|
108
|
+
# Tests that need to disable transactional fixures should delete the user's
|
|
109
|
+
# API token after completion.
|
|
110
|
+
def set_http_token_user(user, token_code = nil)
|
|
111
|
+
if user.nil?
|
|
112
|
+
request.env.delete 'HTTP_AUTHORIZATION'
|
|
113
|
+
return self
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
credential = Tokens::Api.where(user_id: user.id).first
|
|
117
|
+
credential ||= Tokens::Api.random_for(user)
|
|
118
|
+
unless token_code.nil?
|
|
119
|
+
credential.code = token_code
|
|
120
|
+
credential.save!
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
request.env['HTTP_AUTHORIZATION'] = "Token #{credential.code}"
|
|
124
|
+
self
|
|
125
|
+
end
|
|
98
126
|
end # module Authpwn::ControllerTestExtensions
|
|
99
127
|
|
|
100
128
|
end # namespace Authpwn
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'active_model'
|
|
2
|
+
require 'active_support'
|
|
3
|
+
|
|
4
|
+
# :nodoc: namespace
|
|
5
|
+
module Authpwn
|
|
6
|
+
|
|
7
|
+
# :nodoc: namespace
|
|
8
|
+
module UserExtensions
|
|
9
|
+
|
|
10
|
+
# Augments the User model with a password virtual attribute.
|
|
11
|
+
module ApiTokenField
|
|
12
|
+
extend ActiveSupport::Concern
|
|
13
|
+
|
|
14
|
+
# Credentials::Password instance associated with this user.
|
|
15
|
+
def api_token_credential
|
|
16
|
+
credentials.find { |c| c.instance_of?(Tokens::Api) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The code from the user's API token credential.
|
|
20
|
+
#
|
|
21
|
+
# Creates an API token if the user doesn't already have one.
|
|
22
|
+
def api_token
|
|
23
|
+
credential = self.api_token_credential || Tokens::Api.random_for(self)
|
|
24
|
+
credential.code
|
|
25
|
+
end
|
|
26
|
+
end # module Authpwn::UserExtensions::ApiTokenField
|
|
27
|
+
|
|
28
|
+
end # module Authpwn::UserExtensions
|
|
29
|
+
|
|
30
|
+
end # module Authpwn
|
|
@@ -16,14 +16,6 @@ module PasswordField
|
|
|
16
16
|
confirmation: { allow_nil: true }
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
module ClassMethods
|
|
20
|
-
# The user who has a certain e-mail, or nil if the e-mail is unclaimed.
|
|
21
|
-
def with_email(email)
|
|
22
|
-
credential = Credentials::Email.where(name: email).includes(:user).first
|
|
23
|
-
credential && credential.user
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
19
|
# Credentials::Password instance associated with this user.
|
|
28
20
|
def password_credential
|
|
29
21
|
credentials.find { |c| c.instance_of?(Credentials::Password) }
|
data/lib/authpwn_rails.rb
CHANGED
|
@@ -14,12 +14,14 @@ module Authpwn
|
|
|
14
14
|
|
|
15
15
|
# Contains extensions to the User model.
|
|
16
16
|
module UserExtensions
|
|
17
|
+
autoload :ApiTokenField, 'authpwn_rails/user_extensions/api_token_field.rb'
|
|
17
18
|
autoload :EmailField, 'authpwn_rails/user_extensions/email_field.rb'
|
|
18
19
|
autoload :PasswordField, 'authpwn_rails/user_extensions/password_field.rb'
|
|
19
20
|
end
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
require 'authpwn_rails/http_basic.rb'
|
|
24
|
+
require 'authpwn_rails/http_token.rb'
|
|
23
25
|
require 'authpwn_rails/routes.rb'
|
|
24
26
|
require 'authpwn_rails/session.rb'
|
|
25
27
|
require 'authpwn_rails/test_extensions.rb'
|
|
@@ -27,7 +29,7 @@ require 'authpwn_rails/test_extensions.rb'
|
|
|
27
29
|
if defined?(Rails)
|
|
28
30
|
require 'authpwn_rails/engine.rb'
|
|
29
31
|
|
|
30
|
-
# HACK(
|
|
32
|
+
# HACK(pwnall): this works around a known Rails bug
|
|
31
33
|
# https://rails.lighthouseapp.com/projects/8994/tickets/1905-apphelpers-within-plugin-not-being-mixed-in
|
|
32
34
|
require File.expand_path('../../app/helpers/session_helper.rb', __FILE__)
|
|
33
35
|
ActionController::Base.helper SessionHelper
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
class ApiTokenTest < ActiveSupport::TestCase
|
|
4
|
+
def setup
|
|
5
|
+
@credential = Tokens::Api.new
|
|
6
|
+
@credential.code = 'AyCMIixa5C7BBqU-XFI7l7IaUFJ4zQZPmcK6oNb3FLo'
|
|
7
|
+
@credential.user = users(:bill)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
test 'setup' do
|
|
11
|
+
assert @credential.valid?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test 'code required' do
|
|
15
|
+
@credential.code = nil
|
|
16
|
+
assert !@credential.valid?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test 'code uniqueness' do
|
|
20
|
+
@credential.code = credentials(:jane_token).code
|
|
21
|
+
assert !@credential.valid?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
test 'user required' do
|
|
25
|
+
@credential.user = nil
|
|
26
|
+
assert !@credential.valid?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
test 'user uniqueness' do
|
|
30
|
+
@credential.user = credentials(:john_api_token).user
|
|
31
|
+
assert !@credential.valid?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
test 'spend does nothing' do
|
|
35
|
+
credential = credentials(:john_api_token)
|
|
36
|
+
assert_equal Tokens::Api, credential.class, 'bad setup'
|
|
37
|
+
|
|
38
|
+
assert_no_difference 'Credential.count' do
|
|
39
|
+
credential.spend
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test 'expired?' do
|
|
44
|
+
@credential.updated_at = Time.now - 1.year
|
|
45
|
+
assert_equal false, @credential.expired?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
test 'spend does not update old token' do
|
|
49
|
+
old_updated_at = @credential.updated_at = Time.now - 1.year
|
|
50
|
+
@credential.spend
|
|
51
|
+
assert_equal old_updated_at, @credential.updated_at
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
test 'random_for' do
|
|
55
|
+
user = users(:jane)
|
|
56
|
+
credential = nil
|
|
57
|
+
assert_difference 'Credential.count', 1 do
|
|
58
|
+
credential = Tokens::Api.random_for user
|
|
59
|
+
end
|
|
60
|
+
saved_credential = Tokens::Base.with_code(credential.code).first
|
|
61
|
+
assert saved_credential, 'token was not saved'
|
|
62
|
+
assert_equal saved_credential, credential, 'wrong token returned'
|
|
63
|
+
assert_equal user, saved_credential.user
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -21,7 +21,7 @@ class TokenCredentialTest < ActiveSupport::TestCase
|
|
|
21
21
|
assert !@credential.valid?
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
test 'user
|
|
24
|
+
test 'user required' do
|
|
25
25
|
@credential.user = nil
|
|
26
26
|
assert !@credential.valid?
|
|
27
27
|
end
|
|
@@ -46,7 +46,7 @@ class TokenCredentialTest < ActiveSupport::TestCase
|
|
|
46
46
|
|
|
47
47
|
test 'with_code' do
|
|
48
48
|
john = 'YZ-Fo8HX6_NyU6lVZXYi6cMDLV5eAgt35UTF5l8bD6A'
|
|
49
|
-
|
|
49
|
+
john_email = 'bDSU4tzfjuob79e3R0ykLcOGTBBYvuBWWJ9V06tQrCE'
|
|
50
50
|
jane = '6TXe1vv7BgOw0BkJ1hzUKO6G08fLk4sVfJ3wPDZHS-c'
|
|
51
51
|
bogus = 'AyCMIixa5C7BBqU-XFI7l7IaUFJ4zQZPmcK6oNb3FLo'
|
|
52
52
|
assert_equal credentials(:john_token),
|
|
@@ -54,7 +54,7 @@ class TokenCredentialTest < ActiveSupport::TestCase
|
|
|
54
54
|
assert_equal credentials(:jane_token),
|
|
55
55
|
Tokens::Base.with_code(jane).first!
|
|
56
56
|
assert_equal credentials(:john_email_token),
|
|
57
|
-
Tokens::Base.with_code(
|
|
57
|
+
Tokens::Base.with_code(john_email).first
|
|
58
58
|
assert_nil Tokens::Base.with_code(bogus).first
|
|
59
59
|
assert_raise ActiveRecord::RecordNotFound do
|
|
60
60
|
Tokens::Base.with_code('john@gmail.com').first!
|
|
@@ -77,13 +77,27 @@ class TokenCredentialTest < ActiveSupport::TestCase
|
|
|
77
77
|
|
|
78
78
|
test 'class authenticate' do
|
|
79
79
|
john = 'YZ-Fo8HX6_NyU6lVZXYi6cMDLV5eAgt35UTF5l8bD6A'
|
|
80
|
+
john_email = 'bDSU4tzfjuob79e3R0ykLcOGTBBYvuBWWJ9V06tQrCE'
|
|
80
81
|
jane = '6TXe1vv7BgOw0BkJ1hzUKO6G08fLk4sVfJ3wPDZHS-c'
|
|
81
82
|
bogus = 'AyCMIixa5C7BBqU-XFI7l7IaUFJ4zQZPmcK6oNb3FLo'
|
|
83
|
+
|
|
82
84
|
assert_equal users(:john), Tokens::Base.authenticate(john)
|
|
85
|
+
assert_equal users(:john), Tokens::Base.authenticate(john_email)
|
|
83
86
|
assert_equal users(:jane), Tokens::Base.authenticate(jane)
|
|
84
87
|
assert_equal :invalid, Tokens::Base.authenticate(bogus)
|
|
85
88
|
end
|
|
86
89
|
|
|
90
|
+
test 'class authenticate with non-base class' do
|
|
91
|
+
john = 'YZ-Fo8HX6_NyU6lVZXYi6cMDLV5eAgt35UTF5l8bD6A'
|
|
92
|
+
john_email = 'bDSU4tzfjuob79e3R0ykLcOGTBBYvuBWWJ9V06tQrCE'
|
|
93
|
+
bogus = 'AyCMIixa5C7BBqU-XFI7l7IaUFJ4zQZPmcK6oNb3FLo'
|
|
94
|
+
|
|
95
|
+
assert_equal :invalid, Tokens::EmailVerification.authenticate(john)
|
|
96
|
+
assert_equal users(:john),
|
|
97
|
+
Tokens::EmailVerification.authenticate(john_email)
|
|
98
|
+
assert_equal :invalid, Tokens::EmailVerification.authenticate(bogus)
|
|
99
|
+
end
|
|
100
|
+
|
|
87
101
|
test 'class authenticate on expired tokens' do
|
|
88
102
|
john = 'YZ-Fo8HX6_NyU6lVZXYi6cMDLV5eAgt35UTF5l8bD6A'
|
|
89
103
|
jane = '6TXe1vv7BgOw0BkJ1hzUKO6G08fLk4sVfJ3wPDZHS-c'
|
data/test/helpers/routes.rb
CHANGED
|
@@ -11,6 +11,9 @@ def setup_authpwn_routes
|
|
|
11
11
|
resource :http_basic, controller: 'http_basic' do
|
|
12
12
|
collection { get :bouncer }
|
|
13
13
|
end
|
|
14
|
+
resource :http_token, controller: 'http_token' do
|
|
15
|
+
collection { get :bouncer }
|
|
16
|
+
end
|
|
14
17
|
|
|
15
18
|
authpwn_session controller: 'bare_session', method_names: 'bare_session',
|
|
16
19
|
omniauth_path_prefix: '/bare_auth'
|
|
@@ -83,8 +83,8 @@ class HttpBasicControllerTest < ActionController::TestCase
|
|
|
83
83
|
assert_equal "User: #{jane_id}", response.body
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
test "invalid
|
|
87
|
-
get :show, {},
|
|
86
|
+
test "invalid authpwn_suid in session" do
|
|
87
|
+
get :show, {}, authpwn_suid: 'random@user.com'
|
|
88
88
|
assert_response :success
|
|
89
89
|
assert_nil assigns(:current_user)
|
|
90
90
|
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
# Mock controller used for testing session handling.
|
|
4
|
+
class HttpTokenController < ApplicationController
|
|
5
|
+
authenticates_using_http_token
|
|
6
|
+
|
|
7
|
+
def show
|
|
8
|
+
if current_user
|
|
9
|
+
render text: "User: #{current_user.id}"
|
|
10
|
+
else
|
|
11
|
+
render text: "No user"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def bouncer
|
|
16
|
+
bounce_to_http_token
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class HttpTokenControllerTest < ActionController::TestCase
|
|
21
|
+
setup do
|
|
22
|
+
@user = users(:john)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test "no user_id in session cookie or header" do
|
|
26
|
+
get :show
|
|
27
|
+
assert_response :success
|
|
28
|
+
assert_nil assigns(:current_user)
|
|
29
|
+
assert_equal 'No user', response.body
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
test "valid user_id in session cookie" do
|
|
33
|
+
set_session_current_user @user
|
|
34
|
+
get :show
|
|
35
|
+
assert_response :success
|
|
36
|
+
assert_nil assigns(:current_user)
|
|
37
|
+
assert_equal 'No user', response.body
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
test "valid user credentials in header" do
|
|
41
|
+
set_http_token_user @user
|
|
42
|
+
get :show
|
|
43
|
+
assert_equal @user, assigns(:current_user)
|
|
44
|
+
assert_equal nil, session_current_user,
|
|
45
|
+
'Token authentication should not update the session'
|
|
46
|
+
|
|
47
|
+
john_id = ActiveRecord::FixtureSet.identify :john
|
|
48
|
+
assert_equal "User: #{john_id}", response.body
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
test "invalid token in header" do
|
|
52
|
+
set_http_token_user @user
|
|
53
|
+
Tokens::Api.where(user_id: @user.id).destroy_all
|
|
54
|
+
get :show
|
|
55
|
+
assert_nil assigns(:current_user)
|
|
56
|
+
assert_equal 'No user', response.body
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
test "uses Tokens::Api.authenticate" do
|
|
60
|
+
Tokens::Api.expects(:authenticate).at_least_once.with('ap1-c0d3').
|
|
61
|
+
returns @user
|
|
62
|
+
set_http_token_user @user, 'ap1-c0d3'
|
|
63
|
+
get :show
|
|
64
|
+
assert_equal @user, assigns(:current_user)
|
|
65
|
+
assert_equal nil, session_current_user,
|
|
66
|
+
'Token authentication should not update the session'
|
|
67
|
+
|
|
68
|
+
john_id = ActiveRecord::FixtureSet.identify :john
|
|
69
|
+
assert_equal "User: #{john_id}", response.body
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
test "reset user credentials in header" do
|
|
73
|
+
set_http_token_user @user
|
|
74
|
+
set_http_token_user nil
|
|
75
|
+
get :show
|
|
76
|
+
assert_nil assigns(:current_user)
|
|
77
|
+
assert_equal 'No user', response.body
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
test "newly created API token in header" do
|
|
81
|
+
user = users(:jane)
|
|
82
|
+
set_http_token_user user
|
|
83
|
+
get :show
|
|
84
|
+
assert_equal user, assigns(:current_user)
|
|
85
|
+
assert_equal nil, session_current_user,
|
|
86
|
+
'Token authentication should not update the session'
|
|
87
|
+
|
|
88
|
+
jane_id = ActiveRecord::FixtureSet.identify :jane
|
|
89
|
+
assert_equal "User: #{jane_id}", response.body
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
test "invalid authpwn_suid in session" do
|
|
93
|
+
get :show, {}, authpwn_suid: 'random@user.com'
|
|
94
|
+
assert_response :success
|
|
95
|
+
assert_nil assigns(:current_user)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
test "valid user bounced to http authentication" do
|
|
99
|
+
set_http_token_user @user
|
|
100
|
+
get :bouncer
|
|
101
|
+
assert_response :forbidden
|
|
102
|
+
assert_template 'session/forbidden'
|
|
103
|
+
assert_select 'a[href="/session"][data-method="delete"]', 'sign out'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
test "valid user bounced in json" do
|
|
107
|
+
set_http_token_user @user
|
|
108
|
+
get :bouncer, format: 'json'
|
|
109
|
+
assert_response :ok
|
|
110
|
+
data = ActiveSupport::JSON.decode response.body
|
|
111
|
+
assert_match(/not allowed/i, data['error'])
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
test "no user_id bounced to http authentication" do
|
|
115
|
+
get :bouncer
|
|
116
|
+
assert_response :unauthorized
|
|
117
|
+
assert_equal 'Token realm="Application"',
|
|
118
|
+
response.headers['WWW-Authenticate']
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
test "no user_id bounced in json" do
|
|
122
|
+
get :bouncer, format: 'json'
|
|
123
|
+
assert_response :unauthorized
|
|
124
|
+
assert_equal 'Token realm="Application"',
|
|
125
|
+
response.headers['WWW-Authenticate']
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
data/test/session_mailer_test.rb
CHANGED
data/test/test_helper.rb
CHANGED
|
@@ -29,5 +29,9 @@ require 'helpers/test_order.rb'
|
|
|
29
29
|
# Simulate Rails' initializer loading.
|
|
30
30
|
require 'authpwn_rails/generators/templates/initializer.rb'
|
|
31
31
|
|
|
32
|
+
# Simulate Rails' autoloading.
|
|
33
|
+
require 'authpwn_rails/generators/templates/session_mailer.rb'
|
|
34
|
+
require 'authpwn_rails/generators/templates/session_controller.rb'
|
|
35
|
+
|
|
32
36
|
# Rails stubbing is only needed by the initializer, and breaks tests.
|
|
33
37
|
require 'helpers/rails_undo.rb'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
class UserWithApiToken < User
|
|
4
|
+
include Authpwn::UserExtensions::ApiTokenField
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class ApiTokenFieldTest < ActiveSupport::TestCase
|
|
8
|
+
def setup
|
|
9
|
+
@john = UserWithApiToken.find_by_id users(:john).id
|
|
10
|
+
@jane = UserWithApiToken.find_by_id users(:jane).id
|
|
11
|
+
@bill = UserWithApiToken.find_by_id users(:bill).id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test 'api_token_credential' do
|
|
15
|
+
assert_equal credentials(:john_api_token), @john.api_token_credential
|
|
16
|
+
assert_equal nil, @jane.api_token_credential
|
|
17
|
+
assert_equal nil, @bill.api_token_credential
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test 'api_token with existing credential' do
|
|
21
|
+
assert_equal credentials(:john_api_token).code, @john.api_token
|
|
22
|
+
assert_equal nil, @jane.api_token_credential
|
|
23
|
+
assert_equal nil, @bill.api_token_credential
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
test 'api_token without existing credential' do
|
|
27
|
+
assert_equal nil, @jane.api_token_credential
|
|
28
|
+
token_code = @jane.api_token
|
|
29
|
+
assert_not_equal nil, @jane.api_token_credential
|
|
30
|
+
assert_equal @jane.api_token_credential.code, token_code
|
|
31
|
+
assert_not_equal credentials(:john_api_token).code, token_code
|
|
32
|
+
assert_equal nil, @bill.api_token_credential
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -8,9 +8,9 @@ class EmailFieldTest < ActiveSupport::TestCase
|
|
|
8
8
|
def setup
|
|
9
9
|
@user = UserWithEmail.new email: 'blah@gmail.com'
|
|
10
10
|
|
|
11
|
-
@john = UserWithEmail.find_by_id
|
|
12
|
-
@jane = UserWithEmail.find_by_id
|
|
13
|
-
@bill = UserWithEmail.find_by_id
|
|
11
|
+
@john = UserWithEmail.find_by_id users(:john).id
|
|
12
|
+
@jane = UserWithEmail.find_by_id users(:jane).id
|
|
13
|
+
@bill = UserWithEmail.find_by_id users(:bill).id
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
test 'setup' do
|
|
@@ -9,9 +9,9 @@ class PasswordFieldTest < ActiveSupport::TestCase
|
|
|
9
9
|
@user = UserWithPassword.new password: 'awesome',
|
|
10
10
|
password_confirmation: 'awesome'
|
|
11
11
|
|
|
12
|
-
@john = UserWithPassword.find_by_id
|
|
13
|
-
@jane = UserWithPassword.find_by_id
|
|
14
|
-
@bill = UserWithPassword.find_by_id
|
|
12
|
+
@john = UserWithPassword.find_by_id users(:john).id
|
|
13
|
+
@jane = UserWithPassword.find_by_id users(:jane).id
|
|
14
|
+
@bill = UserWithPassword.find_by_id users(:bill).id
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
test 'setup' do
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: authpwn_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.18.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Victor Costan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-06-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 4.0.
|
|
19
|
+
version: 4.0.13
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 4.0.
|
|
26
|
+
version: 4.0.13
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.
|
|
33
|
+
version: 1.6.6
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 1.
|
|
40
|
+
version: 1.6.6
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: mocha
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,14 +86,14 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - ">="
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: 0.3.
|
|
89
|
+
version: 0.3.18
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - ">="
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: 0.3.
|
|
96
|
+
version: 0.3.18
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: omniauth
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -114,14 +114,14 @@ dependencies:
|
|
|
114
114
|
requirements:
|
|
115
115
|
- - ">="
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: 0.
|
|
117
|
+
version: 0.18.2
|
|
118
118
|
type: :development
|
|
119
119
|
prerelease: false
|
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
121
|
requirements:
|
|
122
122
|
- - ">="
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: 0.
|
|
124
|
+
version: 0.18.2
|
|
125
125
|
- !ruby/object:Gem::Dependency
|
|
126
126
|
name: sqlite3
|
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -202,6 +202,7 @@ files:
|
|
|
202
202
|
- app/models/credentials/email.rb
|
|
203
203
|
- app/models/credentials/omni_auth_uid.rb
|
|
204
204
|
- app/models/credentials/password.rb
|
|
205
|
+
- app/models/tokens/api.rb
|
|
205
206
|
- app/models/tokens/base.rb
|
|
206
207
|
- app/models/tokens/email_verification.rb
|
|
207
208
|
- app/models/tokens/one_time.rb
|
|
@@ -239,16 +240,19 @@ files:
|
|
|
239
240
|
- lib/authpwn_rails/generators/templates/user.rb
|
|
240
241
|
- lib/authpwn_rails/generators/templates/users.yml
|
|
241
242
|
- lib/authpwn_rails/http_basic.rb
|
|
243
|
+
- lib/authpwn_rails/http_token.rb
|
|
242
244
|
- lib/authpwn_rails/routes.rb
|
|
243
245
|
- lib/authpwn_rails/session.rb
|
|
244
246
|
- lib/authpwn_rails/session_controller.rb
|
|
245
247
|
- lib/authpwn_rails/session_mailer.rb
|
|
246
248
|
- lib/authpwn_rails/session_model.rb
|
|
247
249
|
- lib/authpwn_rails/test_extensions.rb
|
|
250
|
+
- lib/authpwn_rails/user_extensions/api_token_field.rb
|
|
248
251
|
- lib/authpwn_rails/user_extensions/email_field.rb
|
|
249
252
|
- lib/authpwn_rails/user_extensions/password_field.rb
|
|
250
253
|
- lib/authpwn_rails/user_model.rb
|
|
251
254
|
- test/cookie_controller_test.rb
|
|
255
|
+
- test/credentials/api_token_test.rb
|
|
252
256
|
- test/credentials/email_credential_test.rb
|
|
253
257
|
- test/credentials/email_verification_token_test.rb
|
|
254
258
|
- test/credentials/omni_auth_uid_credential_test.rb
|
|
@@ -275,6 +279,7 @@ files:
|
|
|
275
279
|
- test/helpers/test_order.rb
|
|
276
280
|
- test/helpers/view_helpers.rb
|
|
277
281
|
- test/http_basic_controller_test.rb
|
|
282
|
+
- test/http_token_controller_test.rb
|
|
278
283
|
- test/initializer_test.rb
|
|
279
284
|
- test/routes_test.rb
|
|
280
285
|
- test/session_controller_api_test.rb
|
|
@@ -284,6 +289,7 @@ files:
|
|
|
284
289
|
- test/session_test.rb
|
|
285
290
|
- test/test_extensions_test.rb
|
|
286
291
|
- test/test_helper.rb
|
|
292
|
+
- test/user_extensions/api_token_field_test.rb
|
|
287
293
|
- test/user_extensions/email_field_test.rb
|
|
288
294
|
- test/user_extensions/password_field_test.rb
|
|
289
295
|
- test/user_test.rb
|
|
@@ -307,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
307
313
|
version: '0'
|
|
308
314
|
requirements: []
|
|
309
315
|
rubyforge_project:
|
|
310
|
-
rubygems_version: 2.
|
|
316
|
+
rubygems_version: 2.4.6
|
|
311
317
|
signing_key:
|
|
312
318
|
specification_version: 4
|
|
313
319
|
summary: User authentication for Rails 4 applications.
|