jwt_sessions 1.0.1 → 1.0.2

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5168d7361bdf008db2c14204b698bed8926aa0fc
4
- data.tar.gz: 7a218c9787fef9375a260064adaaf69f31d53e78
3
+ metadata.gz: 143a1452f628f1d201801cc8b7b4855de56479fb
4
+ data.tar.gz: e648fe573c4239e2359d808b5fb93e58d253cf59
5
5
  SHA512:
6
- metadata.gz: 5646630d2e046bf3f6519f384e21306ba109127f53cf831d06164e39d8805396f7a3e561a3afe702c647308faca3cee949300726e3e0134e3fb24563c1330981
7
- data.tar.gz: 902ef70ff8adfe56771ebbab3f06b330bf762a81fc13e9c555df0eaab4b8dfd7ca30b95d84355cfaf4bf11c3508c0e015bcba744bf7eb39095d7c4f6b3b9f4c1
6
+ metadata.gz: d81c0bda06caebed8b38ca9649de98c3e5680859beb7059fd5f0534239f1aeb5b859c0e6f0582bb4585de44b7eef83136fa735d1ac2f7fa6107949e82dd777bb
7
+ data.tar.gz: 7e717dc3a0326c81239d1ce12937182bcc5f7d59df884f9eb4e7513f7a398b8c42984b97865e8bdc6f1a3efc75e8b8c96225b04ff76c64adf44f95508cdc57e7
data/README.md CHANGED
@@ -1,8 +1,29 @@
1
1
  # jwt_sessions
2
2
  [![Gem Version](https://badge.fury.io/rb/jwt_sessions.svg)](https://badge.fury.io/rb/jwt_sessions)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/53de11b8334933b1c0ef/maintainability)](https://codeclimate.com/github/tuwukee/jwt_sessions/maintainability)
4
+ [![Build Status](https://travis-ci.org/tuwukee/jwt_sessions.svg?branch=master)](https://travis-ci.org/tuwukee/jwt_sessions)
3
5
 
4
6
  XSS/CSRF safe JWT auth designed for SPA
5
7
 
8
+ ## Table of Contents
9
+
10
+ - [Synopsis](#synopsis)
11
+ - [Installation](#installation)
12
+ - [Getting Started](#getting-started)
13
+ * [Rails integration](#rails-integration)
14
+ * [Non-Rails usage](#non-rails-usage)
15
+ - [Configuration](#configuration)
16
+ + [Redis](#redis)
17
+ + [JWT encryption](#jwt-encryption)
18
+ + [Request headers and cookies names](#request-headers-and-cookies-names)
19
+ + [Expiration time](#expiration-time)
20
+ + [CSRF and cookies](#csrf-and-cookies)
21
+ + [Refresh token hijack protection](#refresh-token-hijack-protection)
22
+ - [Examples](#examples)
23
+ - [TODO](#todo)
24
+ - [Contributing](#contributing)
25
+ - [License](#license)
26
+
6
27
  ## Synopsis
7
28
 
8
29
  Main goal of this gem is to provide configurable, manageable, and safe stateful sessions based on JSON Web Tokens.
@@ -60,7 +81,8 @@ JWTSessions.encryption_key = Rails.application.secrets.secret_jwt_encryption_key
60
81
  ```
61
82
 
62
83
  Generate access/refresh/csrf tokens with a custom payload. \
63
- The payload will be available in the controllers once the access (or refresh) token is authorized.
84
+ The payload will be available in the controllers once the access (or refresh) token is authorized. \
85
+ Access/refresh tokens contain expiration time in their payload. Yet expiration times are also added to the output just in case.
64
86
 
65
87
  ```ruby
66
88
  > payload = { user_id: user.id }
@@ -72,7 +94,9 @@ The payload will be available in the controllers once the access (or refresh) to
72
94
  > session.login
73
95
  => {:csrf=>"BmhxDRW5NAEIx...",
74
96
  :access=>"eyJhbGciOiJIUzI1NiJ9...",
75
- :refresh=>"eyJhbGciOiJIUzI1NiJ9..."}
97
+ :access_expires_at=>"..."
98
+ :refresh=>"eyJhbGciOiJIUzI1NiJ9...",
99
+ :refresh_expires_at=>"..."}
76
100
  ```
77
101
 
78
102
  You can build login controller to receive access, refresh and csrf tokens in exchange for user's login/password. \
@@ -185,7 +209,7 @@ def request_method
185
209
  end
186
210
  ```
187
211
 
188
- Example Sinatra app.
212
+ Example Sinatra app. \
189
213
  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.
190
214
 
191
215
  ```ruby
@@ -231,7 +255,7 @@ class SimpleApp < Sinatra::Base
231
255
  session.refresh(found_token).to_json
232
256
  end
233
257
 
234
- # GEY /payload
258
+ # GET /payload
235
259
  # authorization: Bearer ...
236
260
  get '/payload' do
237
261
  authorize_access_request!
@@ -310,6 +334,11 @@ session = JwtSessions::Session.new(payload: payload)
310
334
  session.refresh(refresh_token) { |refresh_token_uid, access_token_expiration| ... }
311
335
  ```
312
336
 
337
+ ## Examples
338
+
339
+ [Rails API](test/support/dummy_api) \
340
+ [Sinatra API](test/support/dummy_sinatra_api)
341
+
313
342
  ## TODO
314
343
 
315
344
  Ability to specify public and private keys for RSA/EDCSA/EDDSA, there are no default values for keys. \
@@ -1,12 +1,13 @@
1
1
  module JWTSessions
2
2
  class AccessToken
3
- attr_reader :token, :payload, :uid, :expiration, :csrf
3
+ attr_reader :token, :payload, :uid, :expiration, :csrf, :store
4
4
 
5
5
  def initialize(csrf, payload, store, uid = SecureRandom.uuid, expiration = JWTSessions.access_expiration)
6
6
  @csrf = csrf
7
7
  @uid = uid
8
8
  @expiration = expiration
9
9
  @payload = payload
10
+ @store = store
10
11
  @token = Token.encode(payload.merge(uid: uid, exp: expiration.to_i))
11
12
  end
12
13
 
@@ -84,7 +84,11 @@ module JWTSessions
84
84
  end
85
85
 
86
86
  def tokens_hash
87
- { csrf: csrf_token, access: access_token, refresh: refresh_token }
87
+ { csrf: csrf_token,
88
+ access: access_token,
89
+ access_expires_at: Time.at(@_access.expiration.to_i),
90
+ refresh: refresh_token,
91
+ refresh_expires_at: Time.at(@_refresh.expiration.to_i) }
88
92
  end
89
93
 
90
94
  def check_refresh_on_time
@@ -111,7 +115,11 @@ module JWTSessions
111
115
  end
112
116
 
113
117
  def create_refresh_token
114
- @_refresh = RefreshToken.create(@_csrf.encoded, @_access.uid, @_access.expiration, store, @refresh_payload)
118
+ @_refresh = RefreshToken.create(@_csrf.encoded,
119
+ @_access.uid,
120
+ @_access.expiration,
121
+ store,
122
+ @refresh_payload)
115
123
  @refresh_token = @_refresh.token
116
124
  end
117
125
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWTSessions
4
- VERSION = '1.0.1'
4
+ VERSION = '1.0.2'
5
5
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'jwt_sessions'
5
+
6
+ class TestAccessToken < Minitest::Test
7
+ attr_reader :access_token, :uid
8
+
9
+ def setup
10
+ JWTSessions.encryption_key = 'secret key'
11
+ @payload = { user_id: 1 }
12
+ @csrf = JWTSessions::CSRFToken.new
13
+ @uid = SecureRandom.uuid
14
+ @access_token = JWTSessions::AccessToken.create(@csrf.encoded,
15
+ @payload,
16
+ JWTSessions.token_store)
17
+ end
18
+
19
+ def test_csrf
20
+ token = JWTSessions.token_store.fetch_access(access_token.uid)
21
+ assert_equal token[:csrf], access_token.csrf
22
+ access_token.destroy
23
+ end
24
+
25
+ def test_destroy
26
+ JWTSessions::AccessToken.destroy(access_token.uid, JWTSessions.token_store)
27
+ token = JWTSessions.token_store.fetch_access(access_token.uid)
28
+ assert_equal({}, token)
29
+ end
30
+ end
@@ -7,7 +7,7 @@ class TestRefreshToken < Minitest::Test
7
7
  attr_reader :csrf, :token, :access_uid
8
8
 
9
9
  def setup
10
- JWTSessions.encryption_key = '65994c7b523a3232e7aba54d8cbf'
10
+ JWTSessions.encryption_key = 'secure encryption'
11
11
  @access_uid = SecureRandom.uuid
12
12
  @csrf = JWTSessions::CSRFToken.new
13
13
  @token = JWTSessions::RefreshToken.create(@csrf.encoded,
@@ -5,11 +5,11 @@ require 'jwt_sessions'
5
5
 
6
6
  class TestSession < Minitest::Test
7
7
  attr_reader :session, :payload, :tokens
8
- EXPECTED_KEYS = [:access, :csrf, :refresh].freeze
8
+ EXPECTED_KEYS = %i[access access_expires_at csrf refresh refresh_expires_at].freeze
9
9
 
10
10
  def setup
11
- JWTSessions.encryption_key = '65994c7b523a3232e7aba54d8cbf'
12
- @payload = { test: 'test' }
11
+ JWTSessions.encryption_key = 'encrypted'
12
+ @payload = { test: 'secret' }
13
13
  @session = JWTSessions::Session.new(payload: payload)
14
14
  @tokens = session.login
15
15
  end
@@ -7,13 +7,15 @@ class TestToken < Minitest::Test
7
7
  attr_reader :payload
8
8
 
9
9
  def setup
10
- JWTSessions.encryption_key = '65994c7b523a3232e7aba54d8cbf'
11
- @payload = { 'user_id' => 1 }
10
+ JWTSessions.encryption_key = 'super secret'
11
+ @payload = { 'user_id' => 1, 'secret' => 'mystery' }
12
12
  end
13
13
 
14
14
  def test_valid_token_decode
15
15
  token = JWTSessions::Token.encode(payload)
16
- assert_equal payload['user_id'], JWTSessions::Token.decode(token).first['user_id']
16
+ decoded = JWTSessions::Token.decode(token).first
17
+ assert_equal payload['user_id'], decoded['user_id']
18
+ assert_equal payload['secret'], decoded['secret']
17
19
  end
18
20
 
19
21
  def test_invalid_token_decode
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt_sessions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
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-17 00:00:00.000000000 Z
11
+ date: 2018-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.16'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.16'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.11'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.11'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: pry
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +80,20 @@ dependencies:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: '0.11'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
55
97
  description: XSS/CSRF safe JWT auth designed for SPA
56
98
  email: yulia.oletskaya@gmail.com
57
99
  executables: []
@@ -71,6 +113,7 @@ files:
71
113
  - lib/jwt_sessions/session.rb
72
114
  - lib/jwt_sessions/token.rb
73
115
  - lib/jwt_sessions/version.rb
116
+ - test/units/jwt_sessions/test_access_token.rb
74
117
  - test/units/jwt_sessions/test_csrf_token.rb
75
118
  - test/units/jwt_sessions/test_refresh_token.rb
76
119
  - test/units/jwt_sessions/test_session.rb
@@ -102,6 +145,7 @@ specification_version: 4
102
145
  summary: JWT Sessions
103
146
  test_files:
104
147
  - test/units/test_jwt_sessions.rb
148
+ - test/units/jwt_sessions/test_access_token.rb
105
149
  - test/units/jwt_sessions/test_csrf_token.rb
106
150
  - test/units/jwt_sessions/test_refresh_token.rb
107
151
  - test/units/jwt_sessions/test_session.rb