has_jwt_token 0.2.1 → 0.2.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
  SHA256:
3
- metadata.gz: 445d49f22461e8ad189d361639f786cea6723f1e7126a8510e0089879e6c9272
4
- data.tar.gz: '03580907964370e9611b4aff79526bf2f0ef2aa59e4c8728d8770d3e4448af45'
3
+ metadata.gz: 2ad68b66dda0ed71107ef9ee9437ab28c22ac3a67fd1748a93c16ccf5bc3441e
4
+ data.tar.gz: 638f7aafcad887e610ee30db1146c41ebe7d436444a2a34aa87985beee99adc0
5
5
  SHA512:
6
- metadata.gz: a6d5ab98751e620b5f0f46b4283e127a9e7151e4d615d60bb194186d28cf24a36c426fe0612df17d7d40eee26f30e0a53904034694003d5184a83a669e5d67d7
7
- data.tar.gz: d2d841bdb59c585d0bd52aa90b94b6d69d64ac309a1753431c954172b0996455290cef3411d2811ea59216a3184cea9de736d5eb92ad95fdec109b2696428b0d
6
+ metadata.gz: ccc67e129726ec0e7c5b78a46db992051b55d37c405f366cdf6477d333f685dedf5599288561fc30d5ee6bb4d29a7cbe714169544ef268635cc7c21d148ef868
7
+ data.tar.gz: '08efd1b82ccdf00f5459c02a64e845e2eba02bb1b582b2a5c3abe8f13769c0dc53f82e4b9ecdd9208daac06bc13d49bfd10023e313996afc2615056296b81f8b'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- has_jwt_token (0.2.1)
4
+ has_jwt_token (0.2.2)
5
5
  bcrypt
6
6
  jwt
7
7
  rails (>= 5.0, < 7.0)
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  HasJwtToken provides JWT authetication for models which are kean to use `has_secure_password` in Rails app and wants to use it to grant jwt tokens.
4
4
 
5
- This gem is build on top of [Ruby's JWT](https://github.com/jwt/ruby-jwt) gem and it implements `JWT.encode` and `JWT.decode` methods.
5
+ This gem is build on top of [Ruby's JWT](https://github.com/jwt/ruby-jwt) gem and it implements `JWT.encode` and `JWT.decode` (with validation enabled) methods.
6
6
 
7
7
  ## Installation
8
8
 
@@ -53,7 +53,7 @@ end
53
53
  user = User.last
54
54
 
55
55
  user.authenicate(password) # => user with @token
56
- user.auhtenticate_with_jwt(token) # => user with @token
56
+ User.find_with_jwt(token) # => user with @token
57
57
  ```
58
58
 
59
59
  ## Roadmap
@@ -2,4 +2,5 @@
2
2
 
3
3
  require 'active_support/core_ext/module/delegation'
4
4
  require 'has_jwt_token/version'
5
+ require 'has_jwt_token/errors'
5
6
  require 'has_jwt_token/model'
@@ -1,22 +1,63 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Authenticatable
4
- def authenticate(password)
5
- super(password).tap do |authenticated|
6
- @token = authenticated && encode || nil
3
+ require 'has_jwt_token/jwt_proxy'
4
+
5
+ module HasJwtToken
6
+ module Authenticatable
7
+ module ClassMethods
8
+ def find_with_jwt(jwt_token)
9
+ payload = decode!(jwt_token)
10
+ find_by(authenticate_by => payload[authenticate_by])
11
+ &.tap { |model| model.token = model.encode }
12
+ rescue JWT::DecodeError
13
+ raise HasJwtToken::InvalidToken, 'Invalid token has been provided.'
14
+ end
15
+
16
+ private
17
+
18
+ def authenticate_by
19
+ @authenticate_by ||= begin
20
+ auth_by_attr = has_jwt_token.authenticate_by.to_s
21
+ return auth_by_attr if column_names.include?(auth_by_attr)
22
+
23
+ raise HasJwtToken::BadConfiguration, "#{auth_by_attr.inspect} must be one of model attributes."
24
+ end
25
+ end
26
+
27
+ def decode!(token)
28
+ HasJwtToken::JwtProxy.decode!(
29
+ token: token,
30
+ algorithm: has_jwt_token.algorithm,
31
+ secret: has_jwt_token.secret
32
+ )
33
+ end
7
34
  end
8
- end
9
35
 
10
- def authenticate_with_jwt(jwt_token)
11
- authenticated = decode!(jwt_token)
36
+ def self.included(base)
37
+ base.extend(ClassMethods)
38
+ end
39
+
40
+ def authenticate(password)
41
+ super(password).tap do |authenticated|
42
+ @token = authenticated && encode || nil
43
+ end
44
+ end
45
+
46
+ def encode
47
+ HasJwtToken::JwtProxy.encode(
48
+ algorithm: algorithm,
49
+ payload: model_payload.merge(claims_payload),
50
+ secret: secret,
51
+ header_fields: header_fields
52
+ )
53
+ end
54
+
55
+ private
56
+
57
+ delegate :algorithm, :secret, :model_payload, :claims_payload, :header_fields, to: :has_jwt_token
12
58
 
13
- if authenticated
14
- @token = encode
15
- self
16
- else
17
- @token = nil
59
+ def has_jwt_token
60
+ @has_jwt_token ||= self.class.has_jwt_token(self)
18
61
  end
19
- rescue JWT::DecodeError
20
- nil
21
62
  end
22
63
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HasJwtToken
4
+ HasJwtTokenError = Class.new(StandardError)
5
+
6
+ class InvalidToken < HasJwtTokenError; end
7
+ class BadConfiguration < HasJwtTokenError; end
8
+ end
@@ -7,9 +7,7 @@ module HasJwtToken
7
7
  def has_jwt_token(model = nil)
8
8
  @has_jwt_token ||= JwtConfiguration.new
9
9
  yield(@has_jwt_token) if block_given?
10
- @has_jwt_token.tap do |config|
11
- config.model = model if model
12
- end
10
+ @has_jwt_token.tap { |jwt| jwt.model = model if model }
13
11
  end
14
12
  end
15
13
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module HasJwtToken
4
4
  class JwtConfiguration
5
+ DEFAULT_AUTH_ATTRIBUTE = :id
5
6
  CLAIMS = {
6
7
  expiration_time: :exp,
7
8
  not_before_time: :nbf,
@@ -57,7 +58,8 @@ module HasJwtToken
57
58
  end
58
59
  end
59
60
 
60
- def payload(name = nil, value = nil)
61
+ def payload(name = nil, value: nil, auth_by: false)
62
+ @authenticate_by = name if auth_by
61
63
  @payload[name] = value || ->(model) { model.respond_to?(name) && model.public_send(name) } if name
62
64
  end
63
65
 
@@ -77,5 +79,9 @@ module HasJwtToken
77
79
  val.is_a?(Proc) ? val.call : val
78
80
  end
79
81
  end
82
+
83
+ def authenticate_by
84
+ @authenticate_by || DEFAULT_AUTH_ATTRIBUTE
85
+ end
80
86
  end
81
87
  end
@@ -4,31 +4,14 @@ require 'jwt'
4
4
 
5
5
  module HasJwtToken
6
6
  class JwtProxy
7
- attr_reader :algorithm, :payload, :secret, :header_fields
7
+ class << self
8
+ def encode(payload:, secret: '', algorithm: '', header_fields: {})
9
+ JWT.encode(payload, secret, algorithm, header_fields)
10
+ end
8
11
 
9
- def initialize(algorithm: '', payload: {}, secret: '', header_fields: {})
10
- @algorithm = algorithm
11
- @payload = payload
12
- @secret = secret
13
- @header_fields = header_fields
14
- end
15
-
16
- def encode
17
- JWT.encode(payload, secret, algorithm, header_fields)
18
- end
19
-
20
- def decode(token)
21
- JWT.decode(token, secret, false, algorithm: algorithm)[0]
22
- end
23
-
24
- def decode!(token)
25
- JWT.decode(token, secret, true, algorithm: algorithm)[0]
26
- end
27
-
28
- def valid?(token)
29
- decode!(token) && true
30
- rescue JWT::DecodeError
31
- false
12
+ def decode!(token:, secret: '', algorithm: '')
13
+ JWT.decode(token, secret, true, algorithm: algorithm)[0]
14
+ end
32
15
  end
33
16
  end
34
17
  end
@@ -4,18 +4,16 @@ require 'active_model'
4
4
  require 'bcrypt'
5
5
  require 'has_jwt_token/authenticatable'
6
6
  require 'has_jwt_token/has_jwt_model_configuration'
7
- require 'has_jwt_token/jwt_tokenable'
8
7
 
9
8
  module HasJwtToken
10
9
  module Model
11
- attr_reader :token
10
+ attr_accessor :token
12
11
 
13
12
  def self.included(base)
14
13
  base.include(ActiveModel::SecurePassword)
15
14
  base.has_secure_password
16
15
  base.include(Authenticatable)
17
16
  base.extend(HasJwtModelConfiguration)
18
- base.include(JwtTokenable)
19
17
  end
20
18
  end
21
19
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HasJwtToken
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_jwt_token
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jokūbas Pučinskas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-06 00:00:00.000000000 Z
11
+ date: 2021-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcrypt
@@ -167,10 +167,10 @@ files:
167
167
  - has_jwt_token.gemspec
168
168
  - lib/has_jwt_token.rb
169
169
  - lib/has_jwt_token/authenticatable.rb
170
+ - lib/has_jwt_token/errors.rb
170
171
  - lib/has_jwt_token/has_jwt_model_configuration.rb
171
172
  - lib/has_jwt_token/jwt_configuration.rb
172
173
  - lib/has_jwt_token/jwt_proxy.rb
173
- - lib/has_jwt_token/jwt_tokenable.rb
174
174
  - lib/has_jwt_token/model.rb
175
175
  - lib/has_jwt_token/version.rb
176
176
  homepage: https://github.com/pucinsk/has_jwt_token
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'has_jwt_token/jwt_proxy'
4
-
5
- module HasJwtToken
6
- module JwtTokenable
7
- delegate :algorithm, :secret, :claims_payload, :header_fields, to: :has_jwt_token
8
-
9
- def encode
10
- with_jwt_configuration(&:encode)
11
- end
12
-
13
- def decode(token)
14
- with_jwt_configuration { |jwt| jwt.decode(token) }
15
- end
16
-
17
- def decode!(token)
18
- with_jwt_configuration { |jwt| jwt.decode!(token) }
19
- end
20
-
21
- def has_jwt_token
22
- self.class.has_jwt_token(self)
23
- end
24
-
25
- private
26
-
27
- def payload
28
- @payload ||= has_jwt_token.model_payload.merge(claims_payload)
29
- end
30
-
31
- def with_jwt_configuration
32
- yield(jwt_proxy)
33
- end
34
-
35
- def jwt_proxy
36
- @jwt_proxy ||= JwtProxy.new(
37
- algorithm: algorithm,
38
- payload: payload,
39
- secret: secret,
40
- header_fields: header_fields
41
- )
42
- end
43
- end
44
- end