knock 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|