jwt_api 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19e4d4dcf76be937121c8a2559e64417c07c1218b352492985120076db85d4bd
4
- data.tar.gz: ba9ac0f21978e74a0ada2837d6966b0d017b74043ab001948bb6c137184f9089
3
+ metadata.gz: b98af57b80db1d208e37fea555f8840b0ef28d975b450e3d4913e5b43b90e49c
4
+ data.tar.gz: 37ab658dbc48fcaf0dc6fa332f64f85a5a16a654a1b603855df72d4d00d049f1
5
5
  SHA512:
6
- metadata.gz: ba08a36a4111d4ecb70466481fbc67f55b62a831f56c866ce10e754af84e9091c570e5ce594043da49b3ec13cf389332e78beafcc5c30de02d6558a90a75b0a5
7
- data.tar.gz: d57636254090a1e52d2e9e4408a1925fe7b4accb265b32b4a6933cbddd3439bb255ced6e6c84d35f3f99bac36ca26fa97c8c1a4117a00c9f6f516add5f38185d
6
+ metadata.gz: 325cb78e50548492bf4537a0b89b59e2c8bf9541481b9fc75dad97174251b0e2a7697ef5b8183dc67461375614a8fe22f576a8262df63db63116c0a65be04a54
7
+ data.tar.gz: 32143ac809d4b48c0b0afdd0274c04061f4fd0b094c8e35179d59515a0aecbfa5eabd0bb4a0fbf259f95d3e75387bb789741ffd8cd809de412ada9b8fa78db27
data/Gemfile CHANGED
@@ -7,4 +7,4 @@ gemspec
7
7
 
8
8
  gem 'jwt', '~> 2.2', '>= 2.2.3'
9
9
  gem 'rake', '~> 13.0'
10
- # gem 'rspec', '~> 3.0'
10
+ gem 'rspec'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jwt_api (0.1.0)
4
+ jwt_api (0.1.1)
5
5
  jwt (~> 2.2, >= 2.2.3)
6
6
 
7
7
  GEM
@@ -25,13 +25,14 @@ GEM
25
25
  rspec-support (3.10.2)
26
26
 
27
27
  PLATFORMS
28
+ arm64-darwin-21
28
29
  x86_64-darwin-20
29
30
 
30
31
  DEPENDENCIES
31
32
  jwt (~> 2.2, >= 2.2.3)
32
33
  jwt_api!
33
34
  rake (~> 13.0)
34
- rspec (~> 3.0)
35
+ rspec
35
36
 
36
37
  BUNDLED WITH
37
38
  2.2.25
data/README.md CHANGED
@@ -51,7 +51,7 @@ Running via Spring preloader in process 56250
51
51
  == 20210827123255 AddJtiToUsers: migrated (0.0259s) ===========================
52
52
  ```
53
53
 
54
- Feel free to remove the gem from your Gemfile, you now have everything you need in your application.
54
+
55
55
  ## Usage
56
56
 
57
57
  1. Make sure that each user that needs access to the API has a JTI generated.
data/jwt_api-0.1.0.gem ADDED
Binary file
@@ -8,11 +8,7 @@ class Api::BaseController < ApplicationController
8
8
  protected
9
9
 
10
10
  def authenticate_request!
11
- unless user_id_in_token?
12
- render json: { errors: ['Unauthorized'] }, status: :unauthorized
13
- return
14
- end
15
- @current_user = User.find(auth_token[:user_id])
11
+ user_id_in_token?
16
12
  rescue JWT::VerificationError, JWT::DecodeError
17
13
  render json: { errors: ['Unauthorized'] }, status: :unauthorized
18
14
  end
@@ -20,27 +16,33 @@ class Api::BaseController < ApplicationController
20
16
  private
21
17
 
22
18
  def http_token
23
- @http_token ||= if request.headers['Authorization'].present?
24
- request.headers['Authorization'].split.last
25
- end
19
+ @http_token ||= (request.headers['Authorization'].split.last if request.headers['Authorization'].present?)
26
20
  end
27
21
 
28
22
  def auth_token
29
- @auth_token ||= JsonWebToken.decode(http_token)
30
- rescue JWT::ExpiredSignature
31
- render json: { error: 'token expired' }
23
+ @auth_token ||= jwt.decode(http_token)[0].to_h.symbolize_keys!
24
+ return nil if token_expired?
25
+ return @auth_token if @auth_token.present? && @auth_token[:user_id].present? && jti_matches?
26
+ end
27
+
28
+ def token_expired?
29
+ @auth_token[:exp] < Time.now.to_i
32
30
  end
33
31
 
34
32
  def jti_matches?
35
- @current_user = User.find(auth_token[:user_id])
36
- !@current_user.jti.nil? && @current_user.jti == auth_token[:jti]
33
+ @current_user = User.find(@auth_token[:user_id])
34
+ @current_user&.jti == @auth_token[:jti]
37
35
  end
38
36
 
39
37
  def user_id_in_token?
40
- http_token && auth_token && auth_token[:user_id].to_i && jti_matches?
38
+ http_token && auth_token
41
39
  end
42
40
 
43
41
  def user_reset_token_in_params?
44
42
  params[:reset_password_token]
45
43
  end
44
+
45
+ def jwt
46
+ JsonWebToken.new
47
+ end
46
48
  end
@@ -29,11 +29,12 @@ class Api::V1::AuthenticationController < Api::BaseController
29
29
 
30
30
  iat = Time.now.to_i
31
31
  exp = Time.now.to_i + 24 * 3600
32
+
32
33
  {
33
- token: JsonWebToken.encode({ user_id: user.id,
34
- jti: user.jti,
35
- iat: iat,
36
- exp: exp })
34
+ token: jwt.encode({ user_id: user.id,
35
+ jti: user.jti,
36
+ iat: iat,
37
+ exp: exp })
37
38
  }
38
39
  end
39
40
  end
@@ -11,15 +11,14 @@ class Api::V1::PasswordsController < Api::BaseController
11
11
  @user = User.find_by(email: password_params[:email])
12
12
  if @user.nil?
13
13
  render json: { message: 'email not found' }, status: :not_found
14
+ elsif @user.update(
15
+ reset_password_token: SecureRandom.uuid,
16
+ reset_password_sent_at: Time.now
17
+ )
18
+ JwtMailer.reset_password(@user.id, @user.reset_password_token).deliver
19
+ render json: { message: 'reset password instructions sent' }, status: :ok
14
20
  else
15
- @user.reset_password_token = SecureRandom.uuid
16
- @user.reset_password_sent_at = Time.now
17
- if @user.save
18
- JwtMailer.reset_password(@user.id, @user.reset_password_token).deliver
19
- render json: { message: 'reset password instructions sent' }, status: :ok
20
- else
21
- render json: { message: @user.errors }, status: :not_found
22
- end
21
+ render json: { message: @user.errors }, status: :not_found
23
22
  end
24
23
  end
25
24
 
@@ -27,25 +26,22 @@ class Api::V1::PasswordsController < Api::BaseController
27
26
  # with a token in the params, if a succesful response is received, the client can
28
27
  # store the newly issued JWT and redirect the user to the password reset form
29
28
  def verify
30
- @user = User.where(reset_password_token: params[:token]).first
29
+ @user = User.find_by(reset_password_token: params[:token])
31
30
  if @user.nil?
32
31
  render json: { message: 'reset password token not found' }, status: :not_found
33
- elsif @user.reset_password_sent_at < 1.hour.ago
32
+ elsif @user.reset_password_sent_at < 10.minutes.ago
34
33
  render json: { message: 'reset password token has expired' }, status: :not_found
35
34
  else
36
- @user.reset_password_token = nil
37
- @user.reset_password_sent_at = nil
38
- @user.jti = SecureRandom.uuid
39
- @user.save
40
-
41
- iat = Time.now.to_i
42
- exp = Time.now.to_i + 10 * 60
43
-
35
+ @user.update!(
36
+ reset_password_token: nil,
37
+ reset_password_sent_at: nil,
38
+ jti: SecureRandom.uuid
39
+ )
44
40
  render json: {
45
41
  token: JsonWebToken.encode({ user_id: @user.id,
46
42
  jti: @user.jti,
47
- iat: iat,
48
- exp: exp })
43
+ iat: Time.now.to_i,
44
+ exp: Time.now.to_i + 10 * 60 })
49
45
  }, status: :ok
50
46
  end
51
47
  end
@@ -3,6 +3,7 @@
3
3
  # User controller
4
4
  class Api::V1::UsersController < Api::BaseController
5
5
  skip_before_action :authenticate_request!, only: %i[create]
6
+
6
7
  def create
7
8
  unless user_params[:password] == user_params[:password_confirmation]
8
9
  return render json: { message: "passwords don't match" }, status: :unprocessable_entity
@@ -1,11 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # JSON Web Token class
1
4
  class JsonWebToken
2
- def self.encode(payload)
3
- JWT.encode(payload, Rails.application.secrets.secret_key_base)
5
+ def initialize(key = Rails.application.credentials[:secret_key_base], algorithm = 'HS256')
6
+ @key = key
7
+ @algorithm = algorithm
8
+ end
9
+
10
+ def encode(payload)
11
+ JWT.encode(payload, @key, @algorithm)
4
12
  end
5
13
 
6
- def self.decode(token)
7
- HashWithIndifferentAccess.new(JWT.decode(token, Rails.application.secrets.secret_key_base)[0])
8
- rescue StandardError
9
- nil
14
+ def decode(token)
15
+ JWT.decode(token, @key, @algorithm)
10
16
  end
11
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JwtApi
4
- VERSION = "0.1.0"
4
+ VERSION = '0.1.1'
5
5
  end
data/lib/jwt_api.rb CHANGED
@@ -2,32 +2,3 @@
2
2
 
3
3
  require 'jwt'
4
4
  require_relative 'jwt_api/version'
5
-
6
- module JwtApi
7
- class Jwt
8
- def initialize(key, algorithm = 'HS256')
9
- @key = key
10
- @algorithm = algorithm
11
- end
12
-
13
- def encode(payload)
14
- JWT.encode(payload, @key, @algorithm)
15
- end
16
-
17
- def decode(token)
18
- JWT.decode(token, @key, @algorithm)
19
- end
20
- end
21
- end
22
-
23
- class JsonWebToken
24
- def self.encode(payload)
25
- JWT.encode(payload, Rails.application.secrets.secret_key_base)
26
- end
27
-
28
- def self.decode(token)
29
- HashWithIndifferentAccess.new(JWT.decode(token, Rails.application.secrets.secret_key_base)[0])
30
- rescue StandardError
31
- nil
32
- end
33
- end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leo Policastro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-29 00:00:00.000000000 Z
11
+ date: 2022-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
@@ -48,6 +48,7 @@ files:
48
48
  - Rakefile
49
49
  - bin/console
50
50
  - bin/setup
51
+ - jwt_api-0.1.0.gem
51
52
  - jwt_api.gemspec
52
53
  - lib/generators/jwt_api/setup_generator.rb
53
54
  - lib/generators/jwt_api/templates/api/base_controller.rb
@@ -83,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  - !ruby/object:Gem::Version
84
85
  version: '0'
85
86
  requirements: []
86
- rubygems_version: 3.2.22
87
+ rubygems_version: 3.3.3
87
88
  signing_key:
88
89
  specification_version: 4
89
90
  summary: Write a short summary, because RubyGems requires one.