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 +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +3 -2
- data/README.md +1 -1
- data/jwt_api-0.1.0.gem +0 -0
- data/lib/generators/jwt_api/templates/api/base_controller.rb +16 -14
- data/lib/generators/jwt_api/templates/api/v1/authentication_controller.rb +5 -4
- data/lib/generators/jwt_api/templates/api/v1/passwords_controller.rb +16 -20
- data/lib/generators/jwt_api/templates/api/v1/users_controller.rb +1 -0
- data/lib/generators/jwt_api/templates/initializers/json_web_token.rb +12 -6
- data/lib/jwt_api/version.rb +1 -1
- data/lib/jwt_api.rb +0 -29
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b98af57b80db1d208e37fea555f8840b0ef28d975b450e3d4913e5b43b90e49c
|
4
|
+
data.tar.gz: 37ab658dbc48fcaf0dc6fa332f64f85a5a16a654a1b603855df72d4d00d049f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 325cb78e50548492bf4537a0b89b59e2c8bf9541481b9fc75dad97174251b0e2a7697ef5b8183dc67461375614a8fe22f576a8262df63db63116c0a65be04a54
|
7
|
+
data.tar.gz: 32143ac809d4b48c0b0afdd0274c04061f4fd0b094c8e35179d59515a0aecbfa5eabd0bb4a0fbf259f95d3e75387bb789741ffd8cd809de412ada9b8fa78db27
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
jwt_api (0.1.
|
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
|
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
|
-
|
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
|
-
|
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 ||=
|
30
|
-
|
31
|
-
|
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
|
-
|
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
|
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:
|
34
|
-
|
35
|
-
|
36
|
-
|
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.
|
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.
|
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 <
|
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.
|
37
|
-
|
38
|
-
|
39
|
-
|
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:
|
48
|
-
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
|
3
|
-
|
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
|
7
|
-
|
8
|
-
rescue StandardError
|
9
|
-
nil
|
14
|
+
def decode(token)
|
15
|
+
JWT.decode(token, @key, @algorithm)
|
10
16
|
end
|
11
17
|
end
|
data/lib/jwt_api/version.rb
CHANGED
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.
|
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:
|
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.
|
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.
|