knock 1.3.0 → 1.4.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 +8 -8
- data/app/model/knock/auth_token.rb +16 -4
- data/lib/generators/templates/knock.rb +20 -2
- data/lib/knock.rb +8 -2
- data/lib/knock/authenticable.rb +10 -6
- data/lib/knock/version.rb +1 -1
- data/test/dummy/app/controllers/current_users_controller.rb +9 -0
- data/test/dummy/config/routes.rb +1 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +114 -46
- data/test/dummy/test/controllers/current_users_controller_test.rb +23 -0
- data/test/dummy/test/controllers/protected_resources_controller_test.rb +22 -3
- data/test/model/knock/auth_token_test.rb +51 -0
- data/test/test_helper.rb +15 -0
- data/test/tmp/config/initializers/knock.rb +20 -2
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzVhZjdkMGZhZTMxMWVmYTU1MTRiMTU1OWM4ZTdhZTAyYmEzZWZiNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YWYwZTAzM2EwY2MxMzU4Nzg3N2ZmNzkwY2Y5NzhlOWZiOTFiMzVlMg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjhlOTdhZTBkNTE0NjQzMjBjYWE4M2JlMDA1YjI3ODgyZjFkYzhhYThjOWQ3
|
10
|
+
NGQ1ZjllMzBmZjUzZTdmYjRhYTcyYzQ3MDM4YzAxODNlNzkxMzg2MDlkZGVl
|
11
|
+
ODI4ZTE2N2YwMDE1OWViMGIzOGI0ZDQ5ODU5YzU3ODc1ZTc2NWU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MGJjNjQyOWQ3YzA2ZTU0MzY4ZTI3MGFlY2E0ZDdkMjZhNDJjNmI1YTEzMmZi
|
14
|
+
ZDQ3NDA2NGM2YzA1MTc1M2I4MmI2MThjMzc4MTYzZTQwNzA3MGJkYTJkNWFl
|
15
|
+
ZjBjZDk3OGRmMWFkNWY5OTA0NWRlYzhmY2EzM2YxMjdmY2I2YzM=
|
@@ -6,11 +6,13 @@ module Knock
|
|
6
6
|
|
7
7
|
def initialize payload: {}, token: nil
|
8
8
|
if token.present?
|
9
|
-
@payload, _ = JWT.decode token,
|
9
|
+
@payload, _ = JWT.decode token, decode_key, true, options
|
10
10
|
@token = token
|
11
11
|
else
|
12
12
|
@payload = payload
|
13
|
-
@token = JWT.encode
|
13
|
+
@token = JWT.encode claims.merge(payload),
|
14
|
+
secret_key,
|
15
|
+
Knock.token_signature_algorithm
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -19,10 +21,20 @@ module Knock
|
|
19
21
|
end
|
20
22
|
|
21
23
|
private
|
22
|
-
def
|
24
|
+
def secret_key
|
23
25
|
Knock.token_secret_signature_key.call
|
24
26
|
end
|
25
27
|
|
28
|
+
def decode_key
|
29
|
+
Knock.token_public_key || secret_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def options
|
33
|
+
verify_claims.merge({
|
34
|
+
algorithm: Knock.token_signature_algorithm
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
26
38
|
def claims
|
27
39
|
{
|
28
40
|
exp: Knock.token_lifetime.from_now.to_i,
|
@@ -32,7 +44,7 @@ module Knock
|
|
32
44
|
|
33
45
|
def verify_claims
|
34
46
|
{
|
35
|
-
aud: Knock.token_audience,
|
47
|
+
aud: Knock.token_audience, verify_aud: Knock.token_audience.present?
|
36
48
|
}
|
37
49
|
end
|
38
50
|
end
|
@@ -18,8 +18,10 @@ Knock.setup do |config|
|
|
18
18
|
## AuthTokenController parameters. It also uses the same variable to enforce
|
19
19
|
## permitted values in the controller.
|
20
20
|
##
|
21
|
+
## You must raise ActiveRecord::RecordNotFound if the resource cannot be retrieved.
|
22
|
+
##
|
21
23
|
## Default:
|
22
|
-
#
|
24
|
+
# config.current_user_from_handle = -> (handle) { User.find_by! Knock.handle_attr => handle }
|
23
25
|
|
24
26
|
## Current user retrieval when validating token
|
25
27
|
## --------------------------------------------
|
@@ -28,6 +30,8 @@ Knock.setup do |config|
|
|
28
30
|
## By default, it assumes you have a model called `User` and that
|
29
31
|
## the user_id is stored in the 'sub' claim.
|
30
32
|
##
|
33
|
+
## You must raise ActiveRecord::RecordNotFound if the resource cannot be retrieved.
|
34
|
+
##
|
31
35
|
## Default:
|
32
36
|
# config.current_user_from_token = -> (claims) { User.find claims['sub'] }
|
33
37
|
|
@@ -44,7 +48,7 @@ Knock.setup do |config|
|
|
44
48
|
## Audience claim
|
45
49
|
## --------------
|
46
50
|
##
|
47
|
-
## Configure the audience claim to
|
51
|
+
## Configure the audience claim to identify the recipients that the token
|
48
52
|
## is intended for.
|
49
53
|
##
|
50
54
|
## Default:
|
@@ -53,6 +57,13 @@ Knock.setup do |config|
|
|
53
57
|
## If using Auth0, uncomment the line below
|
54
58
|
# config.token_audience = -> { Rails.application.secrets.auth0_client_id }
|
55
59
|
|
60
|
+
## Signature algorithm
|
61
|
+
## -------------------
|
62
|
+
##
|
63
|
+
## Configure the algorithm used to encode the token
|
64
|
+
##
|
65
|
+
## Default:
|
66
|
+
# config.token_signature_algorithm = 'HS256'
|
56
67
|
|
57
68
|
## Signature key
|
58
69
|
## -------------
|
@@ -65,4 +76,11 @@ Knock.setup do |config|
|
|
65
76
|
## If using Auth0, uncomment the line below
|
66
77
|
# config.token_secret_signature_key = -> { JWT.base64url_decode Rails.application.secrets.auth0_client_secret }
|
67
78
|
|
79
|
+
## Public key
|
80
|
+
## ----------
|
81
|
+
##
|
82
|
+
## Configure the public key used to decode tokens, if required.
|
83
|
+
##
|
84
|
+
## Default:
|
85
|
+
# config.token_public_key = nil
|
68
86
|
end
|
data/lib/knock.rb
CHANGED
@@ -6,10 +6,10 @@ module Knock
|
|
6
6
|
self.handle_attr = :email
|
7
7
|
|
8
8
|
mattr_accessor :current_user_from_handle
|
9
|
-
self.current_user_from_handle = ->
|
9
|
+
self.current_user_from_handle = -> handle { User.find_by! Knock.handle_attr => handle }
|
10
10
|
|
11
11
|
mattr_accessor :current_user_from_token
|
12
|
-
self.current_user_from_token = ->
|
12
|
+
self.current_user_from_token = -> claims { User.find claims['sub'] }
|
13
13
|
|
14
14
|
mattr_accessor :token_lifetime
|
15
15
|
self.token_lifetime = 1.day
|
@@ -17,9 +17,15 @@ module Knock
|
|
17
17
|
mattr_accessor :token_audience
|
18
18
|
self.token_audience = nil
|
19
19
|
|
20
|
+
mattr_accessor :token_signature_algorithm
|
21
|
+
self.token_signature_algorithm = 'HS256'
|
22
|
+
|
20
23
|
mattr_accessor :token_secret_signature_key
|
21
24
|
self.token_secret_signature_key = -> { Rails.application.secrets.secret_key_base }
|
22
25
|
|
26
|
+
mattr_accessor :token_public_key
|
27
|
+
self.token_public_key = nil
|
28
|
+
|
23
29
|
# Default way to setup Knock. Run `rails generate knock:install` to create
|
24
30
|
# a fresh initializer with all configuration values.
|
25
31
|
def self.setup
|
data/lib/knock/authenticable.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
module Knock::Authenticable
|
2
|
-
|
2
|
+
def current_user
|
3
|
+
@current_user ||= begin
|
4
|
+
token = params[:token] ||
|
5
|
+
request.headers['Authorization'].match(/^Bearer (.*)$/)[1]
|
3
6
|
|
4
|
-
|
5
|
-
begin
|
6
|
-
token = request.headers['Authorization'].split(' ').last
|
7
|
-
@current_user = Knock::AuthToken.new(token: token).current_user
|
7
|
+
Knock::AuthToken.new(token: token).current_user
|
8
8
|
rescue
|
9
|
-
|
9
|
+
nil
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
def authenticate
|
14
|
+
head :unauthorized unless current_user
|
15
|
+
end
|
12
16
|
end
|
data/lib/knock/version.rb
CHANGED
data/test/dummy/config/routes.rb
CHANGED
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|
data/test/dummy/log/test.log
CHANGED
@@ -1,78 +1,146 @@
|
|
1
|
-
[1m[36m (
|
2
|
-
[1m[35m (1.
|
1
|
+
[1m[36m (4.5ms)[0m [1mCREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "email" varchar NOT NULL, "password_digest" varchar NOT NULL, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) [0m
|
2
|
+
[1m[35m (1.6ms)[0m CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
|
3
3
|
[1m[36m (0.1ms)[0m [1mselect sqlite_version(*)[0m
|
4
|
-
[1m[35m (1.
|
4
|
+
[1m[35m (1.6ms)[0m CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
|
5
5
|
[1m[36m (0.1ms)[0m [1mSELECT version FROM "schema_migrations"[0m
|
6
|
-
[1m[35m (1.
|
6
|
+
[1m[35m (1.5ms)[0m INSERT INTO "schema_migrations" (version) VALUES ('20150713101607')
|
7
7
|
[1m[36mActiveRecord::SchemaMigration Load (0.1ms)[0m [1mSELECT "schema_migrations".* FROM "schema_migrations"[0m
|
8
8
|
[1m[35m (0.1ms)[0m begin transaction
|
9
9
|
[1m[36mFixture Delete (0.2ms)[0m [1mDELETE FROM "users"[0m
|
10
|
-
[1m[35mFixture Insert (0.1ms)[0m INSERT INTO "users" ("email", "password_digest", "created_at", "updated_at", "id") VALUES ('one@example.net', '$2a$04$
|
11
|
-
[1m[36mFixture Insert (0.1ms)[0m [1mINSERT INTO "users" ("email", "password_digest", "created_at", "updated_at", "id") VALUES ('two@example.net', '$2a$04$
|
12
|
-
[1m[35m (
|
10
|
+
[1m[35mFixture Insert (0.1ms)[0m INSERT INTO "users" ("email", "password_digest", "created_at", "updated_at", "id") VALUES ('one@example.net', '$2a$04$8Yam9pqovA3weu3n/l1Z4eJ7SP/xFw2yESJoXUcpqk89Fqn3mpY7C', '2016-01-02 04:04:33', '2016-01-02 04:04:33', 980190962)
|
11
|
+
[1m[36mFixture Insert (0.1ms)[0m [1mINSERT INTO "users" ("email", "password_digest", "created_at", "updated_at", "id") VALUES ('two@example.net', '$2a$04$pPSRVhAc5Awe4myXaw6EF.Xn.hJ/mWlUGSUA5UfiGbmm4l6O5QJ9u', '2016-01-02 04:04:33', '2016-01-02 04:04:33', 298486374)[0m
|
12
|
+
[1m[35m (1.7ms)[0m commit transaction
|
13
|
+
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
14
|
+
------------------------------------------------------
|
15
|
+
Knock::AuthTokenControllerTest: test_responds_with_201
|
16
|
+
------------------------------------------------------
|
17
|
+
[1m[35mUser Load (0.3ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
18
|
+
Processing by Knock::AuthTokenController#create as HTML
|
19
|
+
Parameters: {"auth"=>{"email"=>"one@example.net", "password"=>"[FILTERED]"}}
|
20
|
+
[1m[36mUser Load (0.2ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1[0m [["email", "one@example.net"]]
|
21
|
+
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "one@example.net"]]
|
22
|
+
Completed 201 Created in 7ms (Views: 0.3ms | ActiveRecord: 0.3ms)
|
23
|
+
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
24
|
+
[1m[35m (0.1ms)[0m begin transaction
|
25
|
+
-----------------------------------------------------------------------------
|
26
|
+
Knock::AuthTokenControllerTest: test_responds_with_404_if_user_does_not_exist
|
27
|
+
-----------------------------------------------------------------------------
|
28
|
+
Processing by Knock::AuthTokenController#create as HTML
|
29
|
+
Parameters: {"auth"=>{"email"=>"wrong@example.net", "password"=>"[FILTERED]"}}
|
30
|
+
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1[0m [["email", "wrong@example.net"]]
|
31
|
+
Completed 404 Not Found in 1ms (ActiveRecord: 0.1ms)
|
32
|
+
[1m[35m (0.1ms)[0m rollback transaction
|
33
|
+
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
34
|
+
-----------------------------------------------------------------------------
|
35
|
+
Knock::AuthTokenControllerTest: test_responds_with_404_if_password_is_invalid
|
36
|
+
-----------------------------------------------------------------------------
|
37
|
+
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
38
|
+
Processing by Knock::AuthTokenController#create as HTML
|
39
|
+
Parameters: {"auth"=>{"email"=>"one@example.net", "password"=>"[FILTERED]"}}
|
40
|
+
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1[0m [["email", "one@example.net"]]
|
41
|
+
Completed 404 Not Found in 2ms (ActiveRecord: 0.1ms)
|
42
|
+
[1m[35m (0.1ms)[0m rollback transaction
|
43
|
+
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
44
|
+
-------------------------------------------------------------------------
|
45
|
+
Knock::AuthTokenTest: test_verify_audience_when_token_audience_is_present
|
46
|
+
-------------------------------------------------------------------------
|
47
|
+
[1m[35m (0.1ms)[0m rollback transaction
|
48
|
+
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
49
|
+
-------------------------------------------------
|
50
|
+
Knock::AuthTokenTest: test_encode_tokens_with_RSA
|
51
|
+
-------------------------------------------------
|
52
|
+
[1m[35m (0.1ms)[0m rollback transaction
|
53
|
+
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
54
|
+
-------------------------------------------
|
55
|
+
Knock::AuthTokenTest: test_verify_algorithm
|
56
|
+
-------------------------------------------
|
57
|
+
[1m[35m (0.1ms)[0m rollback transaction
|
58
|
+
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
59
|
+
----------------------------------------------------
|
60
|
+
Knock::AuthTokenTest: test_decode_RSA_encoded_tokens
|
61
|
+
----------------------------------------------------
|
62
|
+
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
63
|
+
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
64
|
+
[1m[35m (0.1ms)[0m begin transaction
|
65
|
+
-------------------------------------------------------------------------------------------
|
66
|
+
ProtectedResourcesControllerTest: test_responds_with_unauthorized_with_invalid_token_in_url
|
67
|
+
-------------------------------------------------------------------------------------------
|
68
|
+
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", 980190962]]
|
69
|
+
Processing by ProtectedResourcesController#index as HTML
|
70
|
+
Parameters: {"token"=>"invalid"}
|
71
|
+
Filter chain halted as :authenticate rendered or redirected
|
72
|
+
Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms)
|
73
|
+
[1m[35m (0.1ms)[0m rollback transaction
|
13
74
|
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
14
75
|
-----------------------------------------------------------------
|
15
76
|
ProtectedResourcesControllerTest: test_responds_with_unauthorized
|
16
77
|
-----------------------------------------------------------------
|
78
|
+
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
79
|
+
Processing by ProtectedResourcesController#index as HTML
|
80
|
+
Filter chain halted as :authenticate rendered or redirected
|
81
|
+
Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms)
|
82
|
+
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
83
|
+
[1m[35m (0.1ms)[0m begin transaction
|
84
|
+
----------------------------------------------------------------------------------------------
|
85
|
+
ProtectedResourcesControllerTest: test_responds_with_unauthorized_with_invalid_token_in_header
|
86
|
+
----------------------------------------------------------------------------------------------
|
87
|
+
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", 980190962]]
|
17
88
|
Processing by ProtectedResourcesController#index as HTML
|
18
89
|
Filter chain halted as :authenticate rendered or redirected
|
19
90
|
Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms)
|
20
91
|
[1m[35m (0.1ms)[0m rollback transaction
|
21
92
|
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
22
|
-
|
23
|
-
ProtectedResourcesControllerTest:
|
24
|
-
|
25
|
-
[1m[35mUser Load (0.
|
93
|
+
------------------------------------------------------------------------------
|
94
|
+
ProtectedResourcesControllerTest: test_responds_with_success_with_token_in_url
|
95
|
+
------------------------------------------------------------------------------
|
96
|
+
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
26
97
|
Processing by ProtectedResourcesController#index as HTML
|
98
|
+
Parameters: {"token"=>"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NTE3OTM4NzQsImF1ZCI6bnVsbCwic3ViIjo5ODAxOTA5NjJ9.o7HWlffQZN6ss8gZk4Nyl70T8TXpNFoVhr3lBZ5Jvnc"}
|
27
99
|
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", 980190962]]
|
28
|
-
Completed 200 OK in
|
100
|
+
Completed 200 OK in 1ms (ActiveRecord: 0.1ms)
|
29
101
|
[1m[35m (0.1ms)[0m rollback transaction
|
30
|
-
[1m[36m (0.
|
102
|
+
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
31
103
|
------------------------------------------------------------------------------
|
32
104
|
ProtectedResourcesControllerTest: test_has_a_current_user_after_authentication
|
33
105
|
------------------------------------------------------------------------------
|
34
106
|
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
35
107
|
Processing by ProtectedResourcesController#index as HTML
|
36
|
-
[1m[36mUser Load (0.
|
37
|
-
Completed 200 OK in
|
108
|
+
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", 980190962]]
|
109
|
+
Completed 200 OK in 1ms (ActiveRecord: 0.1ms)
|
38
110
|
[1m[35m (0.1ms)[0m rollback transaction
|
39
111
|
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
40
|
-
|
41
|
-
|
42
|
-
|
112
|
+
---------------------------------------------------------------------------------------
|
113
|
+
ProtectedResourcesControllerTest: test_responds_with_success_with_valid_token_in_header
|
114
|
+
---------------------------------------------------------------------------------------
|
43
115
|
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
44
|
-
Processing by
|
45
|
-
Parameters: {"auth"=>{"email"=>"one@example.net", "password"=>"[FILTERED]"}}
|
46
|
-
[1m[36mUser Load (0.2ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1[0m [["email", "one@example.net"]]
|
47
|
-
[1m[35mUser Load (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "one@example.net"]]
|
48
|
-
Completed 201 Created in 3ms (Views: 0.2ms | ActiveRecord: 0.2ms)
|
49
|
-
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
50
|
-
[1m[35m (0.1ms)[0m begin transaction
|
51
|
-
-----------------------------------------------------------------------------
|
52
|
-
Knock::AuthTokenControllerTest: test_responds_with_404_if_password_is_invalid
|
53
|
-
-----------------------------------------------------------------------------
|
116
|
+
Processing by ProtectedResourcesController#index as HTML
|
54
117
|
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", 980190962]]
|
55
|
-
|
56
|
-
Parameters: {"auth"=>{"email"=>"one@example.net", "password"=>"[FILTERED]"}}
|
57
|
-
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "one@example.net"]]
|
58
|
-
Completed 404 Not Found in 2ms (ActiveRecord: 0.1ms)
|
59
|
-
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
60
|
-
[1m[35m (0.0ms)[0m begin transaction
|
61
|
-
-----------------------------------------------------------------------------
|
62
|
-
Knock::AuthTokenControllerTest: test_responds_with_404_if_user_does_not_exist
|
63
|
-
-----------------------------------------------------------------------------
|
64
|
-
Processing by Knock::AuthTokenController#create as HTML
|
65
|
-
Parameters: {"auth"=>{"email"=>"wrong@example.net", "password"=>"[FILTERED]"}}
|
66
|
-
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1[0m [["email", "wrong@example.net"]]
|
67
|
-
Completed 404 Not Found in 1ms (ActiveRecord: 0.1ms)
|
118
|
+
Completed 200 OK in 1ms (ActiveRecord: 0.1ms)
|
68
119
|
[1m[35m (0.1ms)[0m rollback transaction
|
69
120
|
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
[1m[
|
121
|
+
--------------------------------------------------
|
122
|
+
CurrentUsersControllerTest: test_responds_with_200
|
123
|
+
--------------------------------------------------
|
124
|
+
[1m[35mUser Load (0.2ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
125
|
+
Processing by CurrentUsersController#show as HTML
|
126
|
+
[1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m [["id", 980190962]]
|
127
|
+
Completed 200 OK in 1ms (ActiveRecord: 0.1ms)
|
128
|
+
[1m[35m (0.1ms)[0m rollback transaction
|
74
129
|
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
130
|
+
---------------------------------------------------------------------------
|
131
|
+
CurrentUsersControllerTest: test_responds_with_404_if_user_is_not_logged_in
|
132
|
+
---------------------------------------------------------------------------
|
133
|
+
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
|
134
|
+
Processing by CurrentUsersController#show as HTML
|
135
|
+
Completed 404 Not Found in 0ms (ActiveRecord: 0.0ms)
|
136
|
+
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
137
|
+
[1m[35m (0.1ms)[0m begin transaction
|
75
138
|
----------------------------------------------------------------
|
76
139
|
InstallGeneratorTest: test_Assert_all_files_are_properly_created
|
77
140
|
----------------------------------------------------------------
|
78
|
-
[1m[
|
141
|
+
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
142
|
+
[1m[35m (0.1ms)[0m begin transaction
|
143
|
+
---------------------------------------
|
144
|
+
KnockTest: test_setup_block_yields_self
|
145
|
+
---------------------------------------
|
146
|
+
[1m[36m (0.1ms)[0m [1mrollback transaction[0m
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CurrentUsersControllerTest < ActionController::TestCase
|
4
|
+
setup do
|
5
|
+
@user = users(:one)
|
6
|
+
@token = Knock::AuthToken.new(payload: { sub: @user.id }).token
|
7
|
+
end
|
8
|
+
|
9
|
+
def authenticate token: @token
|
10
|
+
@request.env['HTTP_AUTHORIZATION'] = "Bearer #{token}"
|
11
|
+
end
|
12
|
+
|
13
|
+
test "responds with 404 if user is not logged in" do
|
14
|
+
get :show
|
15
|
+
assert_response :not_found
|
16
|
+
end
|
17
|
+
|
18
|
+
test "responds with 200" do
|
19
|
+
authenticate
|
20
|
+
get :show
|
21
|
+
assert_response :success
|
22
|
+
end
|
23
|
+
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ProtectedResourcesControllerTest < ActionController::TestCase
|
4
|
-
def
|
4
|
+
def setup
|
5
5
|
@user = users(:one)
|
6
6
|
@token = Knock::AuthToken.new(payload: { sub: @user.id }).token
|
7
|
-
|
7
|
+
end
|
8
|
+
|
9
|
+
def authenticate token: @token
|
10
|
+
@request.env['HTTP_AUTHORIZATION'] = "Bearer #{token}"
|
8
11
|
end
|
9
12
|
|
10
13
|
test "responds with unauthorized" do
|
@@ -12,12 +15,28 @@ class ProtectedResourcesControllerTest < ActionController::TestCase
|
|
12
15
|
assert_response :unauthorized
|
13
16
|
end
|
14
17
|
|
15
|
-
test "responds with success
|
18
|
+
test "responds with success with valid token in header" do
|
16
19
|
authenticate
|
17
20
|
get :index
|
18
21
|
assert_response :success
|
19
22
|
end
|
20
23
|
|
24
|
+
test "responds with unauthorized with invalid token in header" do
|
25
|
+
authenticate token: "invalid"
|
26
|
+
get :index
|
27
|
+
assert_response :unauthorized
|
28
|
+
end
|
29
|
+
|
30
|
+
test "responds with success with token in url" do
|
31
|
+
get :index, token: @token
|
32
|
+
assert_response :success
|
33
|
+
end
|
34
|
+
|
35
|
+
test "responds with unauthorized with invalid token in url" do
|
36
|
+
get :index, token: "invalid"
|
37
|
+
assert_response :unauthorized
|
38
|
+
end
|
39
|
+
|
21
40
|
test "has a current_user after authentication" do
|
22
41
|
authenticate
|
23
42
|
get :index
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'jwt'
|
3
|
+
|
4
|
+
module Knock
|
5
|
+
class AuthTokenTest < ActiveSupport::TestCase
|
6
|
+
test "verify algorithm" do
|
7
|
+
Knock.token_signature_algorithm = 'RS256'
|
8
|
+
key = Knock.token_secret_signature_key.call
|
9
|
+
|
10
|
+
token = JWT.encode({sub: '1'}, key, 'HS256')
|
11
|
+
|
12
|
+
assert_raises(JWT::IncorrectAlgorithm) {
|
13
|
+
AuthToken.new(token: token)
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
test "decode RSA encoded tokens" do
|
18
|
+
user = users(:one)
|
19
|
+
rsa_private = OpenSSL::PKey::RSA.generate 2048
|
20
|
+
Knock.token_public_key = rsa_private.public_key
|
21
|
+
Knock.token_signature_algorithm = 'RS256'
|
22
|
+
|
23
|
+
token = JWT.encode({sub: user.id}, rsa_private, 'RS256')
|
24
|
+
|
25
|
+
assert_nothing_raised { AuthToken.new(token: token) }
|
26
|
+
end
|
27
|
+
|
28
|
+
test "encode tokens with RSA" do
|
29
|
+
rsa_private = OpenSSL::PKey::RSA.generate 2048
|
30
|
+
Knock.token_secret_signature_key = -> { rsa_private }
|
31
|
+
Knock.token_signature_algorithm = 'RS256'
|
32
|
+
|
33
|
+
token = AuthToken.new(payload: {sub: '1'}).token
|
34
|
+
|
35
|
+
payload, header = JWT.decode token, rsa_private.public_key, true
|
36
|
+
assert_equal payload['sub'], '1'
|
37
|
+
assert_equal header['alg'], 'RS256'
|
38
|
+
end
|
39
|
+
|
40
|
+
test "verify audience when token_audience is present" do
|
41
|
+
Knock.token_audience = 'bar'
|
42
|
+
key = Knock.token_secret_signature_key.call
|
43
|
+
|
44
|
+
token = JWT.encode({sub: 'foo'}, key, 'HS256')
|
45
|
+
|
46
|
+
assert_raises(JWT::InvalidAudError) {
|
47
|
+
AuthToken.new token: token
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -21,3 +21,18 @@ if ActiveSupport::TestCase.respond_to?(:fixture_path=)
|
|
21
21
|
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
22
22
|
ActiveSupport::TestCase.fixtures :all
|
23
23
|
end
|
24
|
+
|
25
|
+
# Make sure knock global configuration is reset before every tests
|
26
|
+
# to avoid order dependent failures.
|
27
|
+
class ActiveSupport::TestCase
|
28
|
+
setup :reset_knock_configuration
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def reset_knock_configuration
|
33
|
+
Knock.token_signature_algorithm = 'HS256'
|
34
|
+
Knock.token_secret_signature_key = -> { Rails.application.secrets.secret_key_base }
|
35
|
+
Knock.token_public_key = nil
|
36
|
+
Knock.token_audience = nil
|
37
|
+
end
|
38
|
+
end
|
@@ -18,8 +18,10 @@ Knock.setup do |config|
|
|
18
18
|
## AuthTokenController parameters. It also uses the same variable to enforce
|
19
19
|
## permitted values in the controller.
|
20
20
|
##
|
21
|
+
## You must raise ActiveRecord::RecordNotFound if the resource cannot be retrieved.
|
22
|
+
##
|
21
23
|
## Default:
|
22
|
-
#
|
24
|
+
# config.current_user_from_handle = -> (handle) { User.find_by! Knock.handle_attr => handle }
|
23
25
|
|
24
26
|
## Current user retrieval when validating token
|
25
27
|
## --------------------------------------------
|
@@ -28,6 +30,8 @@ Knock.setup do |config|
|
|
28
30
|
## By default, it assumes you have a model called `User` and that
|
29
31
|
## the user_id is stored in the 'sub' claim.
|
30
32
|
##
|
33
|
+
## You must raise ActiveRecord::RecordNotFound if the resource cannot be retrieved.
|
34
|
+
##
|
31
35
|
## Default:
|
32
36
|
# config.current_user_from_token = -> (claims) { User.find claims['sub'] }
|
33
37
|
|
@@ -44,7 +48,7 @@ Knock.setup do |config|
|
|
44
48
|
## Audience claim
|
45
49
|
## --------------
|
46
50
|
##
|
47
|
-
## Configure the audience claim to
|
51
|
+
## Configure the audience claim to identify the recipients that the token
|
48
52
|
## is intended for.
|
49
53
|
##
|
50
54
|
## Default:
|
@@ -53,6 +57,13 @@ Knock.setup do |config|
|
|
53
57
|
## If using Auth0, uncomment the line below
|
54
58
|
# config.token_audience = -> { Rails.application.secrets.auth0_client_id }
|
55
59
|
|
60
|
+
## Signature algorithm
|
61
|
+
## -------------------
|
62
|
+
##
|
63
|
+
## Configure the algorithm used to encode the token
|
64
|
+
##
|
65
|
+
## Default:
|
66
|
+
# config.token_signature_algorithm = 'HS256'
|
56
67
|
|
57
68
|
## Signature key
|
58
69
|
## -------------
|
@@ -65,4 +76,11 @@ Knock.setup do |config|
|
|
65
76
|
## If using Auth0, uncomment the line below
|
66
77
|
# config.token_secret_signature_key = -> { JWT.base64url_decode Rails.application.secrets.auth0_client_secret }
|
67
78
|
|
79
|
+
## Public key
|
80
|
+
## ----------
|
81
|
+
##
|
82
|
+
## Configure the public key used to decode tokens, if required.
|
83
|
+
##
|
84
|
+
## Default:
|
85
|
+
# config.token_public_key = nil
|
68
86
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arnaud MESUREUR
|
@@ -9,20 +9,20 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-01-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - ! '>='
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '4.2'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ! '>='
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '4.2'
|
28
28
|
- !ruby/object:Gem::Dependency
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- test/dummy/app/assets/javascripts/application.js
|
94
94
|
- test/dummy/app/assets/stylesheets/application.css
|
95
95
|
- test/dummy/app/controllers/application_controller.rb
|
96
|
+
- test/dummy/app/controllers/current_users_controller.rb
|
96
97
|
- test/dummy/app/controllers/protected_resources_controller.rb
|
97
98
|
- test/dummy/app/helpers/application_helper.rb
|
98
99
|
- test/dummy/app/models/user.rb
|
@@ -128,12 +129,14 @@ files:
|
|
128
129
|
- test/dummy/public/422.html
|
129
130
|
- test/dummy/public/500.html
|
130
131
|
- test/dummy/public/favicon.ico
|
132
|
+
- test/dummy/test/controllers/current_users_controller_test.rb
|
131
133
|
- test/dummy/test/controllers/protected_resources_controller_test.rb
|
132
134
|
- test/dummy/test/fixtures/users.yml
|
133
135
|
- test/dummy/test/models/user_test.rb
|
134
136
|
- test/fixtures/users.yml
|
135
137
|
- test/generators/install_generator_test.rb
|
136
138
|
- test/knock_test.rb
|
139
|
+
- test/model/knock/auth_token_test.rb
|
137
140
|
- test/test_helper.rb
|
138
141
|
- test/tmp/config/initializers/knock.rb
|
139
142
|
homepage: https://github.com/nsarno/knock
|
@@ -167,6 +170,7 @@ test_files:
|
|
167
170
|
- test/dummy/app/assets/javascripts/application.js
|
168
171
|
- test/dummy/app/assets/stylesheets/application.css
|
169
172
|
- test/dummy/app/controllers/application_controller.rb
|
173
|
+
- test/dummy/app/controllers/current_users_controller.rb
|
170
174
|
- test/dummy/app/controllers/protected_resources_controller.rb
|
171
175
|
- test/dummy/app/helpers/application_helper.rb
|
172
176
|
- test/dummy/app/models/user.rb
|
@@ -202,11 +206,13 @@ test_files:
|
|
202
206
|
- test/dummy/public/422.html
|
203
207
|
- test/dummy/public/500.html
|
204
208
|
- test/dummy/public/favicon.ico
|
209
|
+
- test/dummy/test/controllers/current_users_controller_test.rb
|
205
210
|
- test/dummy/test/controllers/protected_resources_controller_test.rb
|
206
211
|
- test/dummy/test/fixtures/users.yml
|
207
212
|
- test/dummy/test/models/user_test.rb
|
208
213
|
- test/fixtures/users.yml
|
209
214
|
- test/generators/install_generator_test.rb
|
210
215
|
- test/knock_test.rb
|
216
|
+
- test/model/knock/auth_token_test.rb
|
211
217
|
- test/test_helper.rb
|
212
218
|
- test/tmp/config/initializers/knock.rb
|