jwt-rails 0.0.1
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 +7 -0
- data/README.md +106 -0
- data/lib/generators/jwt_rails/USAGE +8 -0
- data/lib/generators/jwt_rails/jwt_rails_generator.rb +27 -0
- data/lib/generators/jwt_rails/templates/application_controller.rb +37 -0
- data/lib/generators/jwt_rails/templates/authentication_controller.rb +22 -0
- data/lib/generators/jwt_rails/templates/json_web_token.rb +13 -0
- data/lib/generators/jwt_rails/templates/user.rb +9 -0
- data/lib/generators/jwt_rails/templates/users_controller.rb +54 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f6d25580486b96a786e98b4b0856526101e13451b66950f2980d6484b1dca293
|
4
|
+
data.tar.gz: 344c2bb6bcf75e9757d0b51afe6973c1f65aaba44a493427565ebe559052fae4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d427d22c40a1d1bb1e54ec1b00e2a0e7d13ad3f72a6faf79d6f90265518496bae6bdc58dd1d87477060e2130a541d36fed48a85768b1ee1e0e131fe32d3c5e92
|
7
|
+
data.tar.gz: 0dc9820ed2b37cb22dac5253104c675831080a7fa0889b11c3ad6f1f04c14541cd563ef76c4fc7320d771ee495302c6ecfae36457692abe3a0d14896895fd042
|
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# README
|
2
|
+
jwt-rails project developed for helping Authenticate your rails rest-api project<br/>
|
3
|
+
you can fast develop project with jwt-rails<br/>
|
4
|
+
I used reference following websites<br/>
|
5
|
+
https://guides.rubyonrails.org/generators.html#creating-generators-with-generators <br/>
|
6
|
+
https://medium.com/binar-academy/rails-api-jwt-authentication-a04503ea3248 <br/>
|
7
|
+
|
8
|
+
## Require
|
9
|
+
* rails api only project ```rails new my_api --api``` https://guides.rubyonrails.org/api_app.html
|
10
|
+
* You don't have User Model, It will generate User Model
|
11
|
+
* 'rails', '~> 3.2.0'
|
12
|
+
|
13
|
+
## Getting Started
|
14
|
+
1. Add gem in Gemfile
|
15
|
+
```yaml
|
16
|
+
gem 'jwt-rails', '~> 0.0.1'
|
17
|
+
```
|
18
|
+
OR
|
19
|
+
```yaml
|
20
|
+
gem 'jwt-rails', :git => "git://github.com/x1wins/jwt-rails.git"
|
21
|
+
```
|
22
|
+
|
23
|
+
2. Generate JWT class, User Model, Endpoint
|
24
|
+
```bash
|
25
|
+
rails generate jwt_rails
|
26
|
+
rake db:migrate
|
27
|
+
```
|
28
|
+
|
29
|
+
3. Endpoint
|
30
|
+
1. Create User
|
31
|
+
```bash
|
32
|
+
curl -d '{"user": {"name":"ChangWoo", "username":"helloworld", "email":"x1wins@changwoo.org", "password":"hello1234", "password_confirmation":"hello1234"}}' -H "Content-Type: application/json" -X POST -i http://localhost:3000/users
|
33
|
+
```
|
34
|
+
2. Login
|
35
|
+
```bash
|
36
|
+
curl -d '{"email":"x1wins@changwoo.org", "password":"hello1234"}' -H "Content-Type: application/json" -X POST http://localhost:3000/auth/login | jq
|
37
|
+
{
|
38
|
+
"token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1NzcyMjkwOTl9.an-cp7gWzEuufwvWPo3SFXzpxL_G1wvNpm6g7W_gdQU",
|
39
|
+
"exp": "12-24-2019 15:11",
|
40
|
+
"username": "helloworld"
|
41
|
+
}
|
42
|
+
```
|
43
|
+
3. Token Usage <br/>
|
44
|
+
If you have Post scaffold. you can use following curl command
|
45
|
+
1. Fail Case - Wrong token
|
46
|
+
```bash
|
47
|
+
curl -X GET -i http://localhost:3000/posts
|
48
|
+
HTTP/1.1 401 Unauthorized
|
49
|
+
```
|
50
|
+
2. Success Case
|
51
|
+
```bash
|
52
|
+
curl -X GET -i http://localhost:3000/posts -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1NzcyMjkwOTl9.an-cp7gWzEuufwvWPo3SFXzpxL_G1wvNpm6g7W_gdQU"
|
53
|
+
HTTP/1.1 200 OK
|
54
|
+
```
|
55
|
+
|
56
|
+
4. Scaffold Example
|
57
|
+
1. Use ```user:references``` in scaffold code
|
58
|
+
```bash
|
59
|
+
rails g scaffold post body:string user:references published:boolean
|
60
|
+
```
|
61
|
+
2. Authenticate <br/>
|
62
|
+
Insert ```before_action :authorize_request``` code into Controller
|
63
|
+
```ruby
|
64
|
+
class PostsController < ApplicationController
|
65
|
+
before_action :authorize_request
|
66
|
+
|
67
|
+
//...other code
|
68
|
+
|
69
|
+
end
|
70
|
+
```
|
71
|
+
3. Authorize <br/>
|
72
|
+
https://stackoverflow.com/questions/17594939/check-if-current-user-is-the-owner-of-a-resource-and-allow-edit-delete-actions/57279448#57279448 <br/>
|
73
|
+
1. Insert ```is_owner_object``` code into Controller <br/>
|
74
|
+
2. Append ```merge(user_id: @current_user.id)``` to post_params method
|
75
|
+
```ruby
|
76
|
+
class PostsController < ApplicationController
|
77
|
+
before_action :authorize_request
|
78
|
+
before_action :set_post, only: [:show, :update, :destroy]
|
79
|
+
before_action only: [:edit, :update, :destroy] do
|
80
|
+
is_owner_object @post ##your object
|
81
|
+
end
|
82
|
+
|
83
|
+
//...other code
|
84
|
+
|
85
|
+
def post_params
|
86
|
+
params.require(:post).permit(:body).merge(user_id: @current_user.id)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
```
|
90
|
+
4. Test with CURL
|
91
|
+
1. Create
|
92
|
+
```bash
|
93
|
+
curl -X POST -i http://localhost:3000/posts -d '{"post": {"body":"sample body text sample"}}' -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1NzcyMzY1NTJ9.0pRv-wnQPdQd1WoaA5mSPDWagfGCk---kwO7pSmKkUg"
|
94
|
+
```
|
95
|
+
2. Index
|
96
|
+
```bash
|
97
|
+
curl -X GET -i http://localhost:3000/posts -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1NzcyMzY1NTJ9.0pRv-wnQPdQd1WoaA5mSPDWagfGCk---kwO7pSmKkUg"
|
98
|
+
```
|
99
|
+
|
100
|
+
|
101
|
+
## Contribute
|
102
|
+
How to build gem
|
103
|
+
```bash
|
104
|
+
gem build jwt-rails.gemspec
|
105
|
+
gem install jwt-rails-0.0.1.gem
|
106
|
+
```
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class JwtRailsGenerator < Rails::Generators::Base
|
2
|
+
source_root File.expand_path('templates', __dir__)
|
3
|
+
|
4
|
+
def copy_jwt_rails_file
|
5
|
+
# Use Json Web Token (JWT) for token based authentication
|
6
|
+
gem 'jwt'
|
7
|
+
# Use ActiveModel has_secure_password
|
8
|
+
gem 'bcrypt', '~> 3.1.7'
|
9
|
+
|
10
|
+
route "resources :users, param: :_username"
|
11
|
+
route "post '/auth/login', to: 'authentication#login'"
|
12
|
+
route "get '/*a', to: 'application#not_found'"
|
13
|
+
|
14
|
+
copy_file "json_web_token.rb", "lib/json_web_token.rb"
|
15
|
+
copy_file "application_controller.rb", "app/controllers/application_controller.rb"
|
16
|
+
|
17
|
+
generate "model", "user name:string username:string email:string password_digest:string"
|
18
|
+
copy_file "user.rb", "app/models/user.rb"
|
19
|
+
generate "controller", "users"
|
20
|
+
copy_file "users_controller.rb", "app/controllers/users_controller.rb"
|
21
|
+
generate "controller", "authentication"
|
22
|
+
copy_file "authentication_controller.rb", "app/controllers/authentication_controller.rb"
|
23
|
+
|
24
|
+
puts "Genenrate Finish"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'json_web_token'
|
2
|
+
|
3
|
+
class ApplicationController < ActionController::API
|
4
|
+
|
5
|
+
def not_found
|
6
|
+
render json: { error: 'not_found' }
|
7
|
+
end
|
8
|
+
|
9
|
+
def authorize_request
|
10
|
+
header = request.headers['Authorization']
|
11
|
+
header = header.split(' ').last if header
|
12
|
+
begin
|
13
|
+
@decoded = JsonWebToken.decode(header)
|
14
|
+
@current_user = User.find(@decoded[:user_id])
|
15
|
+
rescue ActiveRecord::RecordNotFound => e
|
16
|
+
render json: { errors: e.message }, status: :unauthorized
|
17
|
+
rescue JWT::DecodeError => e
|
18
|
+
render json: { errors: e.message }, status: :unauthorized
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def is_owner user_id
|
23
|
+
unless user_id == current_user.id
|
24
|
+
render json: nil, status: :forbidden
|
25
|
+
return
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def is_owner_object data
|
30
|
+
if data.nil? or data.user_id.nil?
|
31
|
+
return render status: :not_found
|
32
|
+
else
|
33
|
+
is_owner data.user_id
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class AuthenticationController < ApplicationController
|
2
|
+
before_action :authorize_request, except: :login
|
3
|
+
|
4
|
+
# POST /auth/login
|
5
|
+
def login
|
6
|
+
@user = User.find_by_email(params[:email])
|
7
|
+
if @user&.authenticate(params[:password])
|
8
|
+
token = JsonWebToken.encode(user_id: @user.id)
|
9
|
+
time = Time.now + 24.hours.to_i
|
10
|
+
render json: { token: token, exp: time.strftime("%m-%d-%Y %H:%M"),
|
11
|
+
username: @user.username }, status: :ok
|
12
|
+
else
|
13
|
+
render json: { error: 'unauthorized' }, status: :unauthorized
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def login_params
|
20
|
+
params.permit(:email, :password)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class JsonWebToken
|
2
|
+
SECRET_KEY = Rails.application.secrets.secret_key_base.to_s
|
3
|
+
|
4
|
+
def self.encode(payload, exp = 24.hours.from_now)
|
5
|
+
payload[:exp] = exp.to_i
|
6
|
+
JWT.encode(payload, SECRET_KEY)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.decode(token)
|
10
|
+
decoded = JWT.decode(token, SECRET_KEY)[0]
|
11
|
+
HashWithIndifferentAccess.new decoded
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class User < ApplicationRecord
|
2
|
+
has_secure_password
|
3
|
+
validates :email, presence: true, uniqueness: true
|
4
|
+
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
|
5
|
+
validates :username, presence: true, uniqueness: true
|
6
|
+
validates :password,
|
7
|
+
length: { minimum: 6 },
|
8
|
+
if: -> { new_record? || !password.nil? }
|
9
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class UsersController < ApplicationController
|
2
|
+
before_action :authorize_request, except: :create
|
3
|
+
before_action :find_user, except: %i[create index]
|
4
|
+
before_action only: [:show, :update, :destroy] do
|
5
|
+
is_owner_object @user ##your object
|
6
|
+
end
|
7
|
+
|
8
|
+
# GET /users
|
9
|
+
def index
|
10
|
+
@users = User.all
|
11
|
+
render json: @users, status: :ok
|
12
|
+
end
|
13
|
+
|
14
|
+
# GET /users/{username}
|
15
|
+
def show
|
16
|
+
render json: @user, status: :ok
|
17
|
+
end
|
18
|
+
|
19
|
+
# POST /users
|
20
|
+
def create
|
21
|
+
@user = User.new(user_params)
|
22
|
+
if @user.save
|
23
|
+
render json: @user, status: :created
|
24
|
+
else
|
25
|
+
render json: { errors: @user.errors.full_messages },
|
26
|
+
status: :unprocessable_entity
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# PUT /users/{username}
|
31
|
+
def update
|
32
|
+
unless @user.update(user_params)
|
33
|
+
render json: { errors: @user.errors.full_messages },
|
34
|
+
status: :unprocessable_entity
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# DELETE /users/{username}
|
39
|
+
def destroy
|
40
|
+
@user.destroy
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def find_user
|
46
|
+
@user = User.find_by_username!(params[:_username])
|
47
|
+
rescue ActiveRecord::RecordNotFound
|
48
|
+
render json: { errors: 'User not found' }, status: :not_found
|
49
|
+
end
|
50
|
+
|
51
|
+
def user_params
|
52
|
+
params.require(:user).permit(:name, :username, :email, :password, :password_confirmation)
|
53
|
+
end
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jwt-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chang-Woo Rhee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-12-23 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: 3.2.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
27
|
+
description: Generate JWT, User model, controller
|
28
|
+
email: x1wins@changwoo.net
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- README.md
|
34
|
+
- lib/generators/jwt_rails/USAGE
|
35
|
+
- lib/generators/jwt_rails/jwt_rails_generator.rb
|
36
|
+
- lib/generators/jwt_rails/templates/application_controller.rb
|
37
|
+
- lib/generators/jwt_rails/templates/authentication_controller.rb
|
38
|
+
- lib/generators/jwt_rails/templates/json_web_token.rb
|
39
|
+
- lib/generators/jwt_rails/templates/user.rb
|
40
|
+
- lib/generators/jwt_rails/templates/users_controller.rb
|
41
|
+
homepage: https://github.com/x1wins/jwt-rails
|
42
|
+
licenses:
|
43
|
+
- MIT
|
44
|
+
metadata:
|
45
|
+
homepage_uri: https://www.changwoo.org
|
46
|
+
source_code_uri: https://github.com/x1wins/jwt-rails
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubygems_version: 3.1.1
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: JWT, user resource for Auth rest api generator
|
66
|
+
test_files: []
|