jwt_sessions 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -31
  3. data/lib/jwt_sessions/version.rb +1 -1
  4. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfd4418b2bba47f5127afce7c69075372ed995f1
4
- data.tar.gz: 5d51066a3533865f9c329d203f87819b704d47d8
3
+ metadata.gz: 5168d7361bdf008db2c14204b698bed8926aa0fc
4
+ data.tar.gz: 7a218c9787fef9375a260064adaaf69f31d53e78
5
5
  SHA512:
6
- metadata.gz: 39ee0e2618f6e10577e88ed8c574799888c84e73a4d757d800487b30cb901fb6042e7b53a05e57b6b30f7c2f5f46c78c2fd35ec44653b0f6fa99ef5d7fb0a14c
7
- data.tar.gz: 1a84c6f9d28a1b5571d114b9d6fd2fba37dacc3d0f4eec340e5699728425712ccc271374cd94019a3d54bdc258db579da793e00ca61f7fc66274b24557ebde39
6
+ metadata.gz: 5646630d2e046bf3f6519f384e21306ba109127f53cf831d06164e39d8805396f7a3e561a3afe702c647308faca3cee949300726e3e0134e3fb24563c1330981
7
+ data.tar.gz: 902ef70ff8adfe56771ebbab3f06b330bf762a81fc13e9c555df0eaab4b8dfd7ca30b95d84355cfaf4bf11c3508c0e015bcba744bf7eb39095d7c4f6b3b9f4c1
data/README.md CHANGED
@@ -21,7 +21,7 @@ jwt_sessions itself uses `ext` claim and `HS256` signing by default.
21
21
 
22
22
  Put this line in your Gemfile
23
23
 
24
- ```
24
+ ```ruby
25
25
  gem 'jwt_sessions'
26
26
  ```
27
27
 
@@ -39,7 +39,7 @@ bundle install
39
39
 
40
40
  Include `JWTSessions::RailsAuthorization` in your controllers, add `JWTSessions::Errors::Unauthorized` exceptions handling if needed.
41
41
 
42
- ```
42
+ ```ruby
43
43
  class ApplicationController < ActionController::API
44
44
  include JWTSessions::RailsAuthorization
45
45
  rescue_from JWTSessions::Errors::Unauthorized, with: :not_authorized
@@ -55,14 +55,14 @@ end
55
55
  Specify an encryption key for JSON Web Tokens in `config/initializers/jwt_session.rb` \
56
56
  It's adviced to store the key itself within the app secrets.
57
57
 
58
- ```
58
+ ```ruby
59
59
  JWTSessions.encryption_key = Rails.application.secrets.secret_jwt_encryption_key
60
60
  ```
61
61
 
62
62
  Generate access/refresh/csrf tokens with a custom payload. \
63
63
  The payload will be available in the controllers once the access (or refresh) token is authorized.
64
64
 
65
- ```
65
+ ```ruby
66
66
  > payload = { user_id: user.id }
67
67
  => {:user_id=>1}
68
68
 
@@ -80,7 +80,7 @@ Refresh controller - to be able to get a new access token using refresh token af
80
80
  Here is example of a simple login controller, which returns set of tokens as a plain JSON response. \
81
81
  It's also possible to set tokens as cookies in the response instead.
82
82
 
83
- ```
83
+ ```ruby
84
84
  class LoginController < ApplicationController
85
85
  def create
86
86
  user = User.find_by!(email: params[:email])
@@ -97,14 +97,14 @@ end
97
97
 
98
98
  Since it's not required to pass an access token when you want to perform a refresh you may need to have some data in the payload of the refresh token to allow you to construct a payload of the new access token during refresh.
99
99
 
100
- ```
100
+ ```ruby
101
101
  session = JWTSessions::Session.new(payload: payload, refresh_payload: refresh_payload)
102
102
  ```
103
103
 
104
104
  Now you can build a refresh endpoint. To protect the endpoint use before_action `authorize_refresh_request!`. \
105
105
  In the example `found_token` - is a token fetched from request headers or cookies.
106
106
 
107
- ```
107
+ ```ruby
108
108
  class RefreshController < ApplicationController
109
109
  before_action :authorize_refresh_request!
110
110
 
@@ -129,7 +129,7 @@ POST /refresh
129
129
 
130
130
  Now when there're login and refresh endpoints, you can protect the rest of your secure controllers with `before_action :authorize_access_request!`.
131
131
 
132
- ```
132
+ ```ruby
133
133
  class UsersController < ApplicationController
134
134
  before_action :authorize_access_request!
135
135
 
@@ -151,7 +151,7 @@ GET /users
151
151
 
152
152
  The `payload` method is available to fetch encoded data from the token.
153
153
 
154
- ```
154
+ ```ruby
155
155
  def current_user
156
156
  @current_user ||= User.find(payload['user_id'])
157
157
  end
@@ -163,7 +163,7 @@ You must include `JWTSessions::Authorization` module to your auth class and impl
163
163
 
164
164
  1. request_headers
165
165
 
166
- ```
166
+ ```ruby
167
167
  def request_headers
168
168
  # must return hash-like object with request headers
169
169
  end
@@ -171,7 +171,7 @@ end
171
171
 
172
172
  2. request_cookies
173
173
 
174
- ```
174
+ ```ruby
175
175
  def request_cookies
176
176
  # must return hash-like object with request cookies
177
177
  end
@@ -179,22 +179,28 @@ end
179
179
 
180
180
  3. request_method
181
181
 
182
- ```
182
+ ```ruby
183
183
  def request_method
184
184
  # must return current request verb as a string in upcase, f.e. 'GET', 'HEAD', 'POST', 'PATCH', etc
185
185
  end
186
186
  ```
187
187
 
188
- Example Sinatra app
188
+ Example Sinatra app.
189
+ NOTE: Since rack updates HTTP headers by using `HTTP_` prefix, upcasing and using underscores for sake of simplicity JWTSessions tokens header names are converted to rack-style in this example.
189
190
 
190
- ```
191
+ ```ruby
191
192
  require 'sinatra/base'
192
193
 
194
+ JWTSessions.access_header = 'authorization'
195
+ JWTSessions.refresh_header = 'x_refresh_token'
196
+ JWTSessions.csrf_header = 'x_csrf_token'
197
+ JWTSessions.encryption_key = 'secret key'
198
+
193
199
  class SimpleApp < Sinatra::Base
194
200
  include JWTSessions::Authorization
195
201
 
196
202
  def request_headers
197
- request.headers
203
+ env.inject({}){|acc, (k,v)| acc[$1.downcase] = v if k =~ /^http_(.*)/i; acc}
198
204
  end
199
205
 
200
206
  def request_cookies
@@ -205,13 +211,33 @@ class SimpleApp < Sinatra::Base
205
211
  request.request_method
206
212
  end
207
213
 
214
+ before do
215
+ content_type 'application/json'
216
+ end
217
+
218
+ post '/login' do
219
+ access_payload = { key: 'access value' }
220
+ refresh_payload = { key: 'refresh value' }
221
+ session = JWTSessions::Session.new(payload: access_payload, refresh_payload: refresh_payload)
222
+ session.login.to_json
223
+ end
224
+
225
+ # POST /refresh
226
+ # x_refresh_token: ...
208
227
  post '/refresh' do
209
- content_type :json
210
228
  authorize_refresh_request!
211
- session = JWTSessions::Session.new(payload: payload)
229
+ access_payload = { key: 'reloaded access value' }
230
+ session = JWTSessions::Session.new(payload: access_payload, refresh_payload: payload)
212
231
  session.refresh(found_token).to_json
213
232
  end
214
233
 
234
+ # GEY /payload
235
+ # authorization: Bearer ...
236
+ get '/payload' do
237
+ authorize_access_request!
238
+ payload.to_json
239
+ end
240
+
215
241
  ....
216
242
  end
217
243
  ```
@@ -224,7 +250,7 @@ List of configurable settings with their default values.
224
250
 
225
251
  Default token store configurations
226
252
 
227
- ```
253
+ ```ruby
228
254
  JWTSessions.redis_host = '127.0.0.1'
229
255
  JWTSessions.redis_port = '6379'
230
256
  JWTSessions.redis_db_name = 'jwtokens'
@@ -233,28 +259,21 @@ JWTSessions.token_prefix = 'jwt_' # used for redis db keys
233
259
 
234
260
  ##### JWT encryption
235
261
 
236
- ```
262
+ ```ruby
237
263
  JWTSessions.algorithm = 'HS256'
238
264
  ```
239
265
 
240
266
  You need to specify a secret to use for HMAC, this setting doesn't have a default value.
241
267
 
242
- ```
268
+ ```ruby
243
269
  JWTSessions.secret = 'secret'
244
270
  ```
245
271
 
246
- Or you need to specify public and private keys for RSA/EDCSA/EDDSA, there are no default values for keys. You can use instructions from [ruby-jwt](https://github.com/jwt/ruby-jwt) to generate keys corresponding keys.
247
-
248
- ```
249
- JWTSessions.private_key = 'private_key'
250
- JWTSessions.public_key = 'public_key_for_private'
251
- ```
252
-
253
272
  ##### Request headers and cookies names
254
273
 
255
274
  Default request headers/cookies names can be re-configured
256
275
 
257
- ```
276
+ ```ruby
258
277
  JWTSessions.access_header = 'Authorization'
259
278
  JWTSessions.access_cookie = 'jwt_access'
260
279
  JWTSessions.refresh_header = 'X-Refresh-Token'
@@ -266,7 +285,7 @@ JWTSessions.csrf_header = 'X-CSRF-Token'
266
285
 
267
286
  Acces token must have a short life span, while refresh tokens can be stored for a longer time period
268
287
 
269
- ```
288
+ ```ruby
270
289
  JWTSessions.access_exp_time = 3600 # 1 hour in seconds
271
290
  JWTSessions.refresh_exp_time = 604800 # 1 week in seconds
272
291
  ```
@@ -276,7 +295,7 @@ JWTSessions.refresh_exp_time = 604800 # 1 week in seconds
276
295
  In case when you use cookies as your tokens transport it gets vulnerable to CSRF. That's why both login and refresh methods of the `Session` class produce CSRF tokens for you. `Authorization` mixin expects that this token is sent with all requests except GET and HEAD in a header specified among this gem's settings (X-CSRF-Token by default). Verification will be done automatically and `Authorization` exception will be raised in case of mismatch between the token from the header and the one stored in session. \
277
296
  Although you don't need to mitigate BREACH attacks it's still possible to generate a new masked token with the access token
278
297
 
279
- ```
298
+ ```ruby
280
299
  session = JWTSessions::Session.new
281
300
  session.masked_csrf(access_token)
282
301
  ```
@@ -286,11 +305,21 @@ session.masked_csrf(access_token)
286
305
  There is a security recommendation regarding the usage of refresh tokens: only perform refresh when an access token gets expired. \
287
306
  Since sessions are always defined by a pair of tokens and there can't be multiple access tokens for a single refresh token simultaneous usage of the refresh token by multiple users can be easily noticed as refresh will be perfomed before the expiration of the access token by one of the users. Because of that `refresh` method of the `Session` class supports optional block as one of its arguments which will be executed only in case of refresh being performed before the expiration of the access token.
288
307
 
289
- ```
308
+ ```ruby
290
309
  session = JwtSessions::Session.new(payload: payload)
291
310
  session.refresh(refresh_token) { |refresh_token_uid, access_token_expiration| ... }
292
311
  ```
293
312
 
313
+ ## TODO
314
+
315
+ Ability to specify public and private keys for RSA/EDCSA/EDDSA, there are no default values for keys. \
316
+ You can use instructions from [ruby-jwt](https://github.com/jwt/ruby-jwt) to generate keys corresponding keys.
317
+
318
+ ```ruby
319
+ JWTSessions.private_key = 'private_key'
320
+ JWTSessions.public_key = 'public_key_for_private'
321
+ ```
322
+
294
323
  ## Contributing
295
324
 
296
325
  Fork & Pull Request
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = '1.0.0'
4
+ VERSION = '1.0.1'
5
5
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt_sessions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yulia Oletskaya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-16 00:00:00.000000000 Z
11
+ date: 2018-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.4'
27
27
  - !ruby/object:Gem::Dependency