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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWQzZTFhZmNhYTg2YjZmZDhmMzkyZjRkYzRiMTg0ZmE0MTVhOGE1MA==
4
+ MzVhZjdkMGZhZTMxMWVmYTU1MTRiMTU1OWM4ZTdhZTAyYmEzZWZiNw==
5
5
  data.tar.gz: !binary |-
6
- OWRjZDEyZmY3MDk0MTYzM2QwMmM0NDQxYTJjOGEwZWM2ZjBmMjBjYQ==
6
+ YWYwZTAzM2EwY2MxMzU4Nzg3N2ZmNzkwY2Y5NzhlOWZiOTFiMzVlMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZmRkZjFjOGViZTJhNjhmNWFlZmQ5ZGIwMzI2MjQ5YjRiOWI5ZWY3MGRjN2Rj
10
- ZmE5NjY3YzVlNTE1MDAxYmNlOThhYmZkMzBlMjY0ZDI1MmNmYjMzYWY3ODc5
11
- MDZkNjZhYjM5M2EzY2FjMzczNTYyN2Y0MTM5MmMwMTIxZTRjMmE=
9
+ MjhlOTdhZTBkNTE0NjQzMjBjYWE4M2JlMDA1YjI3ODgyZjFkYzhhYThjOWQ3
10
+ NGQ1ZjllMzBmZjUzZTdmYjRhYTcyYzQ3MDM4YzAxODNlNzkxMzg2MDlkZGVl
11
+ ODI4ZTE2N2YwMDE1OWViMGIzOGI0ZDQ5ODU5YzU3ODc1ZTc2NWU=
12
12
  data.tar.gz: !binary |-
13
- M2RlNjA2ZTFjOTdkMDZlMTllNjA1MzViZjIzODNhYTNlZWM2MjNlNjVjZWJi
14
- NzdkNDk5YzIzMWViNzEzMjRhZjEwMjNmNWNmMTZmNjA1NDhlMzU4NDM0NzZk
15
- ZmM2NzA3MzQ5MzVkZDA2NzBkMjljMzY5ZmVjOWZiNWZhOTgxY2E=
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, key, true, verify_claims
9
+ @payload, _ = JWT.decode token, decode_key, true, options
10
10
  @token = token
11
11
  else
12
12
  @payload = payload
13
- @token = JWT.encode(claims.merge(payload), key, 'HS256')
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 key
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, verify_claims: Knock.token_audience.present?
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
- # self.current_user_from_handle = -> (handle) { User.find_by! Knock.handle_attr => handle }
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 indentify the recipients that the token
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 = -> (handle) { User.find_by! Knock.handle_attr => 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 = -> (claims) { User.find claims['sub'] }
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
@@ -1,12 +1,16 @@
1
1
  module Knock::Authenticable
2
- attr_reader :current_user
2
+ def current_user
3
+ @current_user ||= begin
4
+ token = params[:token] ||
5
+ request.headers['Authorization'].match(/^Bearer (.*)$/)[1]
3
6
 
4
- def authenticate
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
- head :unauthorized
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
@@ -1,3 +1,3 @@
1
1
  module Knock
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -0,0 +1,9 @@
1
+ class CurrentUsersController < ApplicationController
2
+ def show
3
+ if current_user
4
+ head :ok
5
+ else
6
+ head :not_found
7
+ end
8
+ end
9
+ end
@@ -1,4 +1,5 @@
1
1
  Rails.application.routes.draw do
2
2
  resources :protected_resources
3
+ resource :current_user
3
4
  mount Knock::Engine => "/knock"
4
5
  end
Binary file
@@ -1,78 +1,146 @@
1
-  (2.9ms) CREATE 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) 
2
-  (1.4ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
1
+  (4.5ms) CREATE 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) 
2
+  (1.6ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
3
3
   (0.1ms) select sqlite_version(*)
4
-  (1.3ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
4
+  (1.6ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
5
5
   (0.1ms) SELECT version FROM "schema_migrations"
6
-  (1.0ms) INSERT INTO "schema_migrations" (version) VALUES ('20150713101607')
6
+  (1.5ms) INSERT INTO "schema_migrations" (version) VALUES ('20150713101607')
7
7
  ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
8
8
   (0.1ms) begin transaction
9
9
  Fixture Delete (0.2ms) DELETE FROM "users"
10
- Fixture Insert (0.1ms) INSERT INTO "users" ("email", "password_digest", "created_at", "updated_at", "id") VALUES ('one@example.net', '$2a$04$0mPmVn/CmWZkmHf15VY.JuVDRXH5EhKuCzFpsKH7.ySvtGWM4WLhW', '2015-07-23 14:58:31', '2015-07-23 14:58:31', 980190962)
11
- Fixture Insert (0.1ms) INSERT INTO "users" ("email", "password_digest", "created_at", "updated_at", "id") VALUES ('two@example.net', '$2a$04$h2eMNW1pZXYVkPzhnOGg3efpsw7/ENPysgUpdAi4o8u0K.wu/omDG', '2015-07-23 14:58:31', '2015-07-23 14:58:31', 298486374)
12
-  (45.0ms) commit transaction
10
+ Fixture Insert (0.1ms) 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
+ Fixture Insert (0.1ms) INSERT 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)
12
+  (1.7ms) commit transaction
13
+  (0.1ms) begin transaction
14
+ ------------------------------------------------------
15
+ Knock::AuthTokenControllerTest: test_responds_with_201
16
+ ------------------------------------------------------
17
+ User Load (0.3ms) 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
+ User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "one@example.net"]]
21
+ User Load (0.1ms) 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
+  (0.1ms) rollback transaction
24
+  (0.1ms) 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
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "wrong@example.net"]]
31
+ Completed 404 Not Found in 1ms (ActiveRecord: 0.1ms)
32
+  (0.1ms) rollback transaction
33
+  (0.1ms) begin transaction
34
+ -----------------------------------------------------------------------------
35
+ Knock::AuthTokenControllerTest: test_responds_with_404_if_password_is_invalid
36
+ -----------------------------------------------------------------------------
37
+ User Load (0.1ms) 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
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "one@example.net"]]
41
+ Completed 404 Not Found in 2ms (ActiveRecord: 0.1ms)
42
+  (0.1ms) rollback transaction
43
+  (0.1ms) begin transaction
44
+ -------------------------------------------------------------------------
45
+ Knock::AuthTokenTest: test_verify_audience_when_token_audience_is_present
46
+ -------------------------------------------------------------------------
47
+  (0.1ms) rollback transaction
48
+  (0.1ms) begin transaction
49
+ -------------------------------------------------
50
+ Knock::AuthTokenTest: test_encode_tokens_with_RSA
51
+ -------------------------------------------------
52
+  (0.1ms) rollback transaction
53
+  (0.1ms) begin transaction
54
+ -------------------------------------------
55
+ Knock::AuthTokenTest: test_verify_algorithm
56
+ -------------------------------------------
57
+  (0.1ms) rollback transaction
58
+  (0.1ms) begin transaction
59
+ ----------------------------------------------------
60
+ Knock::AuthTokenTest: test_decode_RSA_encoded_tokens
61
+ ----------------------------------------------------
62
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
63
+  (0.1ms) rollback transaction
64
+  (0.1ms) begin transaction
65
+ -------------------------------------------------------------------------------------------
66
+ ProtectedResourcesControllerTest: test_responds_with_unauthorized_with_invalid_token_in_url
67
+ -------------------------------------------------------------------------------------------
68
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["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
+  (0.1ms) rollback transaction
13
74
   (0.1ms) begin transaction
14
75
  -----------------------------------------------------------------
15
76
  ProtectedResourcesControllerTest: test_responds_with_unauthorized
16
77
  -----------------------------------------------------------------
78
+ User Load (0.1ms) 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
+  (0.1ms) rollback transaction
83
+  (0.1ms) begin transaction
84
+ ----------------------------------------------------------------------------------------------
85
+ ProtectedResourcesControllerTest: test_responds_with_unauthorized_with_invalid_token_in_header
86
+ ----------------------------------------------------------------------------------------------
87
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["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
   (0.1ms) rollback transaction
21
92
   (0.1ms) begin transaction
22
- -----------------------------------------------------------------------------
23
- ProtectedResourcesControllerTest: test_responds_with_success_if_authenticated
24
- -----------------------------------------------------------------------------
25
- User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
93
+ ------------------------------------------------------------------------------
94
+ ProtectedResourcesControllerTest: test_responds_with_success_with_token_in_url
95
+ ------------------------------------------------------------------------------
96
+ User Load (0.1ms) 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
  User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
28
- Completed 200 OK in 2ms (ActiveRecord: 0.1ms)
100
+ Completed 200 OK in 1ms (ActiveRecord: 0.1ms)
29
101
   (0.1ms) rollback transaction
30
-  (0.0ms) begin transaction
102
+  (0.1ms) begin transaction
31
103
  ------------------------------------------------------------------------------
32
104
  ProtectedResourcesControllerTest: test_has_a_current_user_after_authentication
33
105
  ------------------------------------------------------------------------------
34
106
  User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
35
107
  Processing by ProtectedResourcesController#index as HTML
36
- User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
37
- Completed 200 OK in 0ms (ActiveRecord: 0.0ms)
108
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
109
+ Completed 200 OK in 1ms (ActiveRecord: 0.1ms)
38
110
   (0.1ms) rollback transaction
39
111
   (0.1ms) begin transaction
40
- ------------------------------------------------------
41
- Knock::AuthTokenControllerTest: test_responds_with_201
42
- ------------------------------------------------------
112
+ ---------------------------------------------------------------------------------------
113
+ ProtectedResourcesControllerTest: test_responds_with_success_with_valid_token_in_header
114
+ ---------------------------------------------------------------------------------------
43
115
  User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
44
- Processing by Knock::AuthTokenController#create as HTML
45
- Parameters: {"auth"=>{"email"=>"one@example.net", "password"=>"[FILTERED]"}}
46
- User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "one@example.net"]]
47
- User Load (0.0ms) 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
-  (0.1ms) rollback transaction
50
-  (0.1ms) begin transaction
51
- -----------------------------------------------------------------------------
52
- Knock::AuthTokenControllerTest: test_responds_with_404_if_password_is_invalid
53
- -----------------------------------------------------------------------------
116
+ Processing by ProtectedResourcesController#index as HTML
54
117
  User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
55
- Processing by Knock::AuthTokenController#create as HTML
56
- Parameters: {"auth"=>{"email"=>"one@example.net", "password"=>"[FILTERED]"}}
57
- User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["email", "one@example.net"]]
58
- Completed 404 Not Found in 2ms (ActiveRecord: 0.1ms)
59
-  (0.1ms) rollback transaction
60
-  (0.0ms) 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
- User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1 [["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
   (0.1ms) rollback transaction
69
120
   (0.1ms) begin transaction
70
- ---------------------------------------
71
- KnockTest: test_setup_block_yields_self
72
- ---------------------------------------
73
-  (0.0ms) rollback transaction
121
+ --------------------------------------------------
122
+ CurrentUsersControllerTest: test_responds_with_200
123
+ --------------------------------------------------
124
+ User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
125
+ Processing by CurrentUsersController#show as HTML
126
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 980190962]]
127
+ Completed 200 OK in 1ms (ActiveRecord: 0.1ms)
128
+  (0.1ms) rollback transaction
74
129
   (0.1ms) begin transaction
130
+ ---------------------------------------------------------------------------
131
+ CurrentUsersControllerTest: test_responds_with_404_if_user_is_not_logged_in
132
+ ---------------------------------------------------------------------------
133
+ User Load (0.1ms) 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
+  (0.1ms) rollback transaction
137
+  (0.1ms) begin transaction
75
138
  ----------------------------------------------------------------
76
139
  InstallGeneratorTest: test_Assert_all_files_are_properly_created
77
140
  ----------------------------------------------------------------
78
-  (0.1ms) rollback transaction
141
+  (0.1ms) rollback transaction
142
+  (0.1ms) begin transaction
143
+ ---------------------------------------
144
+ KnockTest: test_setup_block_yields_self
145
+ ---------------------------------------
146
+  (0.1ms) rollback transaction
@@ -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 authenticate
4
+ def setup
5
5
  @user = users(:one)
6
6
  @token = Knock::AuthToken.new(payload: { sub: @user.id }).token
7
- @request.env['HTTP_AUTHORIZATION'] = "Bearer #{@token}"
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 if authenticated" do
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
- # self.current_user_from_handle = -> (handle) { User.find_by! Knock.handle_attr => handle }
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 indentify the recipients that the token
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.3.0
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: 2015-07-23 00:00:00.000000000 Z
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