rails_javascript_web_tokens 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e485184d3005717b26ffcd61cb61642ade757d0ab14b6aaf242ac75b20681eec
4
+ data.tar.gz: 67cbe0eb438167409ec1924094b156cd0d8e4f32722abe79ba113ec22c78b0fd
5
+ SHA512:
6
+ metadata.gz: 85394f3df196be8d67a13432bd3fc0b849a5e1f44c40a77ae0f052975377fb4e2801a7fda604dd5660293670909eac961d6e89840a44ecf6b61ea9f31a5c70ad
7
+ data.tar.gz: 0fe4cc779a9ca450ee7ec2f0ecdccd2f462d420faf3500c071b680915ad36a91fa2a8cad14e0b35937d420b9490d4c9dfb18b193f330618c5e7769c0b34da12f
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 ispirett
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # rails_javascript_web_tokens
2
+
3
+ ## Work in progress
4
+ Simple jwt rails authentication
5
+
6
+ ## Features
7
+ ##### Sign Up
8
+ ##### Sign in
9
+ ##### Authenticate any Controller action
10
+ ##### Refresh Token
11
+ ##### Expiration date for token => default 1.month
12
+
13
+
14
+ ## Installation
15
+ ```ruby
16
+ gem 'rails_javascript_web_tokens', github: "https://github.com/Ispirett/rails_jwt"
17
+ or
18
+ gem 'rails_javascript_web_tokens'
19
+ ```
20
+ then execute:
21
+ ```bash
22
+ $ bundle
23
+ ```
24
+ ```bash
25
+ rails g rails_jwt:install
26
+ ```
27
+ And then:
28
+
29
+ ```bash
30
+ rails db:migrate
31
+ ```
32
+ ## Usage
33
+ * Use authorize_user! helper for authenticating user with token
34
+ ```ruby
35
+ :authorize_user!
36
+ ```
37
+ ```ruby
38
+ class TomController < ApplicationController
39
+ before_action :authorize_user!, only: %w(create update)
40
+ end
41
+ ```
42
+ * Use current_user to access the current logged in user
43
+ ```ruby
44
+ class TomController < ApplicationController
45
+ def create
46
+ current_user.email
47
+ end
48
+ end
49
+ ```
50
+ ## User model
51
+ * This gem creates a user model and handle securing password with bcrypt.
52
+ * After running the gem's install command you will see the code below.
53
+ * The details method is important to the gem.
54
+ * You can add or remove attributes which will affect the response.
55
+
56
+ ```ruby
57
+ def details
58
+ as_json(only: [:id, :email,:created_at])
59
+ end
60
+ ```
61
+
62
+ ## Routes
63
+ * This gem adds routes to your routes file like so.
64
+ * Sign Up /rails_jwt/auth/sign_up
65
+ * Sign In /rails_jwt/auth/sign_in
66
+
67
+ ```ruby
68
+ mount RailsJwt::Engine => "/rails_jwt", as: :rails_jwt
69
+ ```
70
+
71
+
72
+
73
+
74
+
75
+ ## Making requests
76
+ ##### Sign Up
77
+
78
+ ```html
79
+ rails_jwt/auth/sign_up
80
+ ```
81
+
82
+ ```json
83
+ { "user":{ "email":"hit@gmail.com", "password": "foobar", "password_confirmation": "foobar"}}
84
+ ```
85
+ ##### Response
86
+ ```json
87
+ {
88
+ "status": "success",
89
+ "token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE2MzQxNzg2MDd9.eJmaV2_fP8P52LiI9tJx_UTI8nTPxepuADz6KYK_Pew",
90
+ "user": {
91
+ "id": 1,
92
+ "email": "hit@gmail.com",
93
+ "created_at": "2021-10-07T02:30:07.894Z",
94
+ },
95
+ "exp": "07 20 73 01:00"
96
+ }
97
+ ```
98
+
99
+ ## Sign In
100
+ ```html
101
+ rails_jwt/auth/sign_in
102
+
103
+ ```
104
+
105
+ ```json
106
+ { "user":{ "email":"hit@gmail.com", "password": "foobar"}}
107
+ ```
108
+ ##### Response
109
+ ```json
110
+ {
111
+ "status": "success",
112
+ "user": {
113
+ "id": 4,
114
+ "email": "test@gmail.com",
115
+ "created_at": "2021-10-07T17:20:28.592Z"
116
+ },
117
+ "token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo0LCJleHAiOjE2MzM2Mjc2MjJ9.HjMN61WlujV9YYLZAQ3Xog53jbPTugwMrq0rxdNL_Qk",
118
+ "exp": "07-21-73 06:52"
119
+ }
120
+ ```
121
+
122
+ ## Request with token
123
+ * Add token user "AuthToken": '.........' in headers
124
+ ```js
125
+ const api_add_error = async (data) => {
126
+ const token = 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2l.................'
127
+ try {
128
+ const response = await fetch('http://example.com/resource',{
129
+ method: 'POST',
130
+ headers: {
131
+ 'Content-Type': 'application/json',
132
+ 'AuthToken': token
133
+ },
134
+ body: JSON.stringify(data)
135
+ });
136
+ return await response.json()
137
+ }
138
+ catch (e) {
139
+ console.log(e)
140
+ }
141
+ }
142
+ ```
143
+
144
+
145
+ ## Contributing
146
+
147
+
148
+ ## License
149
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1,42 @@
1
+ require 'active_support/concern'
2
+
3
+ module ControllerHelpers
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ def authorize_user!
7
+ header = request.headers[:AuthToken]
8
+ begin
9
+ @decoded = decode(header)
10
+ @current_user = User.find(@decoded[:user_id])
11
+
12
+ rescue ActiveRecord::RecordNotFound => e
13
+ render json: {status: :failed, msg: e.message}, status: :not_found
14
+
15
+ rescue JWT::DecodeError => e
16
+ render json: {status: :failed, refresh_token: refresh_jwt_user(header), msg: e.message}, status: :not_found
17
+ end
18
+ end
19
+
20
+
21
+ def refresh_jwt_user(token)
22
+ begin
23
+ user_id = Jwt.find_by(token: token).user_id
24
+ #=> generate new token
25
+ token = encode(user_id: user_id)
26
+ replace_token = Jwt.find_by(user_id: user_id)
27
+ replace_token.update_attribute(:token, token)
28
+ replace_token.token
29
+ rescue => e
30
+ e
31
+ end
32
+ end
33
+ end
34
+
35
+
36
+ # module ClassMethods
37
+ #
38
+ #
39
+ # end
40
+ #
41
+ # extend ClassMethods
42
+ end
@@ -0,0 +1,4 @@
1
+ module RailsJwt
2
+ class ApplicationController < ::ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,67 @@
1
+ require_dependency "rails_jwt/application_controller"
2
+
3
+ module RailsJwt
4
+ class UsersController < ApplicationController
5
+ include RailsJwt::Controllers::Authentication
6
+ skip_before_action :verify_authenticity_token
7
+ before_action :check_passwords, only: :create
8
+ # gem 'rails_jwt', path:'/Users/ispirett/RubymineProjects/engines/rails_jwt'
9
+
10
+ def create
11
+ @user = User.new(user_params)
12
+ if @user.save
13
+ token = encode(user_id: @user.id)
14
+ # refactor to allow users to configure
15
+ time = Time.now + 1.week.from_now.to_i
16
+ render json: {status: 'success', token: token,user: @user.details, exp: time.strftime('%m %d %y %H:%M')}, status: :ok
17
+ else
18
+ render json: {status: :failed, msg: @user.errors.full_messages}, status: :unauthorized
19
+ end
20
+ end
21
+
22
+ def sign_in
23
+ @user = User.find_by(email: params[:email].downcase)
24
+ if @user&.authenticate(params[:password])
25
+ #=> create new token from JwtAuth
26
+ token = encode(user_id: @user.id)
27
+ time = Time.now + 1.week.from_now.to_i
28
+
29
+ #=> create or update user to jwt model
30
+ if @logged_user = Jwt.find_by(user_id: @user.id)
31
+ @logged_user.update_attribute(:token, token)
32
+ else
33
+ Jwt.create(user_id: @user.id, token: token)
34
+ end
35
+
36
+ render json: {status: :success,user: @user.details, token:token, exp: time.strftime('%m-%d-%y %H:%M')},status: :ok
37
+ else
38
+ render json: {status: :failed, msg: 'email or password is incorrect'}, status: :unauthorized
39
+ end
40
+ end
41
+
42
+
43
+
44
+ private
45
+ def refresh_token
46
+ header = request.headers[:AuthToken]
47
+ render json: {status: :success, refresh_token: refresh_jwt_user(header)}
48
+ end
49
+
50
+ def user_params
51
+ params.require(:user).permit(:email,:password, :password_confirmation )
52
+ end
53
+
54
+ def check_passwords
55
+ if !user_params.include?(:password_confirmation)
56
+ render json: {status: :failed, msg: "Password confirmation can't be black", status: :unauthorize}
57
+ elsif user_params[:password] != user_params[:password_confirmation]
58
+ render json: {status: :failed, msg: "Your passwords do not match." , status: :unauthorize}
59
+ end
60
+ end
61
+ end
62
+
63
+
64
+
65
+
66
+ end
67
+
@@ -0,0 +1,6 @@
1
+ module RailsJwt
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ RailsJwt::Engine.routes.draw do
2
+ match '/auth/sign_in' => "users#sign_in", via: :get, as: :sign_in
3
+ match '/auth/sign_up' => "users#create", via: :post, as: :sign_up
4
+ end
@@ -0,0 +1,43 @@
1
+ module RailsJwt
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root File.expand_path('templates', __dir__)
4
+
5
+ def install_route
6
+ route 'mount RailsJwt::Engine => "/rails_jwt", as: :rails_jwt'
7
+ end
8
+
9
+ def copy_user_model
10
+ copy_file "user.rb", "app/models/user.rb"
11
+ end
12
+
13
+ def copy_jwt_model
14
+ copy_file "jwt.rb", "app/models/jwt.rb"
15
+ end
16
+
17
+ def copy_migrations
18
+ # migration_template 'create_users.rb', 'db/migrate/rails_jtw_create_user.rb', migration_version
19
+ # migration_template 'create_jwts.rb', 'db/migrate/rails_jtw_create_jwts.rb', migration_version
20
+
21
+ copy_file "20211007002206_create_users.rb",
22
+ "db/migrate/20211007002206_create_users.rb"
23
+ copy_file "20211007002344_create_jwts.rb",
24
+ "db/migrate/20211007002344_create_jwts.rb"
25
+
26
+ end
27
+
28
+
29
+
30
+ private
31
+
32
+ def rails5_and_up?
33
+ Rails::VERSION::MAJOR >= 5
34
+ end
35
+
36
+ def migration_version
37
+ if rails5_and_up?
38
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ class CreateUsers < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :email
5
+ t.string :password_digest
6
+ t.timestamps
7
+ end
8
+ add_index :users, :email, unique: true
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class CreateJwts < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :jwts do |t|
4
+ t.string :token
5
+ t.integer :user_id, null: false, foreign_key: true
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ class Jwt < ApplicationRecord
2
+ belongs_to :user
3
+ end
4
+
@@ -0,0 +1,11 @@
1
+ class User < ApplicationRecord
2
+ has_secure_password
3
+ EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
4
+ validates :email, presence: true, format: {with: EMAIL_REGEX}, uniqueness: true
5
+ # validates :name, presence: true, length: {minimum: 3, maximum: 25}
6
+ # validates :username, presence: true,length:{minimum: 3, maximum: 25}
7
+
8
+ def details
9
+ as_json(only: [:id, :email,:created_at])
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module RailsJwt
2
+ module Controllers
3
+ module Authentication
4
+
5
+ SECRET_KEY = ENV.fetch("RAILS_JWT_TOKEN", 'development')
6
+ # TODO refactor to allow users to ad there own expiration date
7
+ def encode(payout, exp = 1.month.from_now)
8
+ payout[:exp] = exp.to_i
9
+ JWT.encode(payout, SECRET_KEY)
10
+
11
+ end
12
+
13
+ def decode(token)
14
+ decode = JWT.decode(token, SECRET_KEY)[0]
15
+ HashWithIndifferentAccess.new decode
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ module RailsJwt
3
+ module Controllers
4
+ module Helpers
5
+ extend ActiveSupport::Concern
6
+ include RailsJwt::Controllers::Authentication
7
+
8
+ included do
9
+ def authorize_user!
10
+ header = request.headers[:AuthToken]
11
+ begin
12
+ @decoded = decode(header)
13
+ @current_user = User.find(@decoded[:user_id])
14
+
15
+ rescue ActiveRecord::RecordNotFound => e
16
+ render json: {status: :failed, msg: e.message}, status: :not_found
17
+
18
+ rescue JWT::DecodeError => e
19
+ render json: {status: :failed, refresh_token: refresh_jwt_user(header), msg: e.message}, status: :not_found
20
+ end
21
+ end
22
+
23
+
24
+ def refresh_jwt_user(token)
25
+ begin
26
+ user_id = Jwt.find_by(token: token).user_id
27
+ #=> generate new token
28
+ token = encode(user_id: user_id)
29
+ replace_token = Jwt.find_by(user_id: user_id)
30
+ replace_token.update_attribute(:token, token)
31
+ replace_token.token
32
+ rescue => e
33
+ e
34
+ end
35
+ end
36
+
37
+ def current_user
38
+ @current_user
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ module RailsJwt
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RailsJwt
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec, fixture: false
7
+ g.fixture_replacement :factory_girl, dir: 'spec/factories'
8
+ g.assets false
9
+ g.helper false
10
+ g.template_engine false
11
+ end
12
+ ActionController::Base.send :include, RailsJwt::Controllers::Helpers
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module RailsJwt
2
+ VERSION = '0.1.0'
3
+ end
data/lib/rails_jwt.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "rails_jwt/version"
2
+ require 'Jwt'
3
+ require 'bcrypt'
4
+ require 'rails_jwt/controllers/authentication'
5
+ require 'rails_jwt/controllers/helpers'
6
+ require "rails_jwt/engine"
7
+
8
+ module RailsJwt
9
+ module Controllers
10
+ autoload :Authentication, 'rails_jwt/controllers/authentication'
11
+ autoload :Helpers, 'rails_jwt/controllers/helpers'
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rails_jwt do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_javascript_web_tokens
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ispirett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.4
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 6.1.4.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 6.1.4
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 6.1.4.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: jwt
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: bcrypt
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 3.1.16
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 3.1.16
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ description: Integrate jwt in your application with a few simple steps
76
+ email:
77
+ - ispirett@gmail.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - MIT-LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - app/controllers/concerns/controller_helpers.rb
86
+ - app/controllers/rails_jwt/application_controller.rb
87
+ - app/controllers/rails_jwt/users_controller.rb
88
+ - app/mailers/rails_jwt/application_mailer.rb
89
+ - config/routes.rb
90
+ - lib/generators/rails_jwt/install_generator.rb
91
+ - lib/generators/rails_jwt/templates/20211007002206_create_users.rb
92
+ - lib/generators/rails_jwt/templates/20211007002344_create_jwts.rb
93
+ - lib/generators/rails_jwt/templates/jwt.rb
94
+ - lib/generators/rails_jwt/templates/user.rb
95
+ - lib/rails_jwt.rb
96
+ - lib/rails_jwt/controllers/authentication.rb
97
+ - lib/rails_jwt/controllers/helpers.rb
98
+ - lib/rails_jwt/engine.rb
99
+ - lib/rails_jwt/version.rb
100
+ - lib/tasks/rails_jwt_tasks.rake
101
+ homepage: https://github.com/Ispirett/rails_jwt
102
+ licenses:
103
+ - MIT
104
+ metadata:
105
+ allowed_push_host: https://rubygems.org
106
+ homepage_uri: https://github.com/Ispirett/rails_jwt
107
+ source_code_uri: https://github.com/Ispirett/rails_jwt
108
+ changelog_uri: https://github.com/Ispirett/rails_jwt/CHANGELOG.md
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubygems_version: 3.1.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: Use jwt with rails no code
128
+ test_files: []