credible 0.11.0 → 0.12.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 +4 -4
- data/README.md +29 -11
- data/app/views/credible/sessions/_session.json.jbuilder +3 -1
- data/app/views/credible/users/_user.json.jbuilder +6 -1
- data/config/initializers/warden.rb +40 -4
- data/config/routes.rb +8 -0
- data/lib/credible/controllers/sessions_controller.rb +19 -1
- data/lib/credible/session.rb +22 -4
- data/lib/credible/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36d4cd634fa34562978e37d5a84169812678c28109d09c58238cb8c5bc2338d5
|
4
|
+
data.tar.gz: edc9471b968557985508ed60f49ae905390b3167d120497b3ea272faed0b423a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 263ef8576aae2c0b1aaad9d1e5710c2eca33e5812accbe1a5d19827b37782bb3a8109ba5a91f77a41fc16a41834d5c4d040358be44017836ed9a22c54ffe6c0c
|
7
|
+
data.tar.gz: f23153d8e705f201acba1ff85c31016f2e1a1e9076016a66083ef8fb7da21a740c0bd2d5031ec4cf4e881ed0f352e3ac662a4592f599f9f70b7960ba7ab56ae9
|
data/README.md
CHANGED
@@ -1,18 +1,22 @@
|
|
1
|
-
|
1
|
+
<h1 id="credible" align="center">Credible</h1>
|
2
2
|
|
3
|
-
|
3
|
+
<p align="center"><strong>Credible</strong> | <a href="https://github.com/thombruce/credible-demo">Demo Repo</a> | <a href="https://github.com/thombruce/helvellyn">Helvellyn</a></p>
|
4
4
|
|
5
|
-
|
6
|
-
[](https://github.com/thombruce/credible/actions)
|
7
|
-
[](https://codecov.io/gh/thombruce/credible)
|
8
|
-
[](https://github.com/thombruce/credible/issues)
|
5
|
+
<p align="center"><a href="https://www.patreon.com/thombruce"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patron"></a></p>
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
<p align="center"><a href="https://rubygems.org/gems/credible"><img src="https://img.shields.io/gem/v/credible?logo=rubygems" alt="Gem"></a>
|
8
|
+
<a href="https://github.com/thombruce/credible/actions"><img src="https://img.shields.io/github/workflow/status/thombruce/credible/CI?logo=github" alt="GitHub Workflow Status"></a>
|
9
|
+
<a href="https://codecov.io/gh/thombruce/credible"><img src="https://img.shields.io/codecov/c/github/thombruce/credible?logo=codecov" alt="Codecov"></a>
|
10
|
+
<a href="https://github.com/thombruce/credible/issues"><img src="https://img.shields.io/github/issues-raw/thombruce/credible?logo=github" alt="GitHub issues"></a></p>
|
14
11
|
|
15
|
-
|
12
|
+
<p align="center"><a href="MIT-LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
13
|
+
<a href="CONTRIBUTING.md"><img src="https://img.shields.io/badge/contributions-welcome-blue.svg" alt="Contributing"></a>
|
14
|
+
<a href="https://discord.gg/YMU87db"><img src="https://img.shields.io/discord/697123984231366716?color=7289da&label=chat&logo=discord" alt="Discord"></a></p>
|
15
|
+
|
16
|
+
<p align="center"><a href="CHANGELOG.md"><img src="https://img.shields.io/badge/Keep%20a%20Changelog-v1.1.0%20adopted-red.svg" alt="Changelog"></a>
|
17
|
+
<a href="CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg" alt="Contributor Covenant"></a></p>
|
18
|
+
|
19
|
+
<p align="center">Credible was extracted from <a href="https://github.com/thombruce/helvellyn">thombruce/helvellyn</a> and is still a work in progress. The goal is to provide JWT and API token based authentication using <a href="https://github.com/wardencommunity/warden/">Warden</a> for Rails API applications.</p>
|
16
20
|
|
17
21
|
## Installation
|
18
22
|
|
@@ -73,6 +77,20 @@ class Session < ApplicationRecord
|
|
73
77
|
end
|
74
78
|
```
|
75
79
|
|
80
|
+
## Calling the API
|
81
|
+
|
82
|
+
To sign up and create a new user, send params in the form `{ user: { email: 'email@example.com', password: 'Pa$$word123!' } }` to `auth/signup` as a `POST` request. On success, this will return `{ access_token: '...', refresh_token: '...' }` that can be used to persist the user's session.
|
83
|
+
|
84
|
+
To sign in a user, send params in the form `{ session: { login: 'email@example.com', password: 'Pa$$word123!' } }` to `auth/login` as a `POST` request. On success, this will return `{ access_token: '...', refresh_token: '...' }` that can be used to persist the user's session.
|
85
|
+
|
86
|
+
To sign out a user, send an empty request to `auth/signout` as a `DELETE` request. On success, this will return no content. It will destroy the session in the database and invalidate any existing tokens. Note: If you are using the access token to authenticate the user on a separate server, it will still remain valid until its expiry.
|
87
|
+
|
88
|
+
To refresh an access token, send params in the form `{ refresh_token: '...' }` to `auth/refresh` as a `POST` request. On success, this will return `{ access_token: '...', refresh_token: '...' }` that can be used to continue the user's session. Note: This will also invalidate the refresh token used to renew the tokens, and provide a new refresh token for next use.
|
89
|
+
|
90
|
+
> **Be careful**
|
91
|
+
>
|
92
|
+
> Credible is still a work in progress and these routes will be subject to change. I'm thinking about keeping them around as sort of a "classic" mode, but I feel like more resource-oriented routes are also desirable. For example, I want to add a `/tokens` endpoint in place of the existing `/refresh` enpoint, because _refresh what?_ It's just more semantically correct.
|
93
|
+
|
76
94
|
## Mailers
|
77
95
|
|
78
96
|
To user Credible's in-built mailers, you must set a hostname for your application. A suitable setting for this in `config/environments/development.rb` might be:
|
@@ -1,5 +1,10 @@
|
|
1
1
|
json.extract! user, :id, :email, :created_at, :updated_at
|
2
2
|
|
3
|
-
|
3
|
+
if @session
|
4
|
+
json.access_token @session.access_token
|
5
|
+
json.jwt @session.access_token
|
6
|
+
|
7
|
+
json.refresh_token @session.refresh_token
|
8
|
+
end
|
4
9
|
|
5
10
|
json.url user_url(user, format: :json)
|
@@ -3,12 +3,13 @@ Rails.application.config.middleware.use Warden::Manager do |config|
|
|
3
3
|
|
4
4
|
config.default_scope = :session
|
5
5
|
|
6
|
-
config.scope_defaults :session, store: false, strategies: [:jwt, :api_token]
|
6
|
+
config.scope_defaults :session, store: false, strategies: [:jwt, :refresh, :api_token]
|
7
7
|
end
|
8
8
|
|
9
9
|
# TODO: See here for how Devise initializes Warden: https://github.com/heartcombo/devise/blob/715192a7709a4c02127afb067e66230061b82cf2/lib/devise/rails.rb
|
10
10
|
# It's also worth perusing the mention of 'warden' in the Devise repo. Interesting strategies at work.
|
11
11
|
|
12
|
+
# TODO: Change to :access_token, maybe maintain :jwt as alias
|
12
13
|
Warden::Strategies.add(:jwt) do
|
13
14
|
def valid?
|
14
15
|
env['HTTP_AUTHORIZATION']
|
@@ -25,14 +26,49 @@ Warden::Strategies.add(:jwt) do
|
|
25
26
|
jwt = header.gsub(pattern, '') if header && header.match(pattern)
|
26
27
|
token =
|
27
28
|
JWT.decode jwt, Rails.application.secrets.secret_key_base, true,
|
28
|
-
iss: Rails.application.class.module_parent_name,
|
29
|
-
|
29
|
+
iss: Rails.application.class.module_parent_name,
|
30
|
+
verify_iss: true, verify_iat: true, verify_expiration: true,
|
31
|
+
algorithm: 'HS256' # [1]
|
32
|
+
rescue JWT::InvalidIssuerError, JWT::InvalidIatError, JWT::ExpiredSignature
|
30
33
|
fail!('Could not authenticate')
|
31
34
|
end
|
32
35
|
|
33
36
|
session = ::Session.find(token[0]['data']['session_id'])
|
34
37
|
success!(session)
|
35
|
-
rescue ActiveRecord::RecordNotFound
|
38
|
+
rescue # ActiveRecord::RecordNotFound
|
39
|
+
fail!('Could not authenticate')
|
40
|
+
end
|
41
|
+
|
42
|
+
def store?
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Warden::Strategies.add(:refresh) do
|
48
|
+
def valid?
|
49
|
+
# params[:refresh_token]
|
50
|
+
env['action_dispatch.request.parameters']['refresh_token'] # https://github.com/wardencommunity/warden/issues/84
|
51
|
+
end
|
52
|
+
|
53
|
+
def env
|
54
|
+
request.env
|
55
|
+
end
|
56
|
+
|
57
|
+
def authenticate!
|
58
|
+
begin
|
59
|
+
jwt = env['action_dispatch.request.parameters']['refresh_token']
|
60
|
+
token =
|
61
|
+
JWT.decode jwt, Rails.application.secrets.secret_key_base, true,
|
62
|
+
iss: Rails.application.class.module_parent_name,
|
63
|
+
verify_iss: true, verify_iat: true, verify_expiration: true,
|
64
|
+
algorithm: 'HS256' # [1]
|
65
|
+
rescue JWT::InvalidIssuerError, JWT::InvalidIatError, JWT::ExpiredSignature
|
66
|
+
fail!('Could not authenticate')
|
67
|
+
end
|
68
|
+
|
69
|
+
session = ::Session.find(token[0]['data']['session_id'])
|
70
|
+
success!(session)
|
71
|
+
rescue # ActiveRecord::RecordNotFound
|
36
72
|
fail!('Could not authenticate')
|
37
73
|
end
|
38
74
|
|
data/config/routes.rb
CHANGED
@@ -2,12 +2,19 @@ Credible::Engine.routes.draw do
|
|
2
2
|
scope format: false, defaults: { format: 'json' } do
|
3
3
|
# /auth/login.json
|
4
4
|
post 'login', to: 'sessions#create'
|
5
|
+
|
6
|
+
# /auth/refresh.json
|
7
|
+
post 'refresh', to: 'sessions#refresh'
|
8
|
+
|
5
9
|
# /auth/reset_password.json
|
6
10
|
post 'reset_password', to: 'users#reset_password'
|
11
|
+
|
7
12
|
# /auth/signup.json
|
8
13
|
post 'signup', to: 'users#create'
|
14
|
+
|
9
15
|
# /auth/confirm.json
|
10
16
|
get 'confirm/:confirmation_token', to: 'users#confirm', as: :confirmation
|
17
|
+
|
11
18
|
# /auth/signout.json
|
12
19
|
delete 'signout', to: 'sessions#destroy'
|
13
20
|
|
@@ -15,6 +22,7 @@ Credible::Engine.routes.draw do
|
|
15
22
|
scope '/account' do
|
16
23
|
# /auth/account/sessions/*.json
|
17
24
|
resources :sessions, except: [:new, :create, :edit, :update]
|
25
|
+
|
18
26
|
# /auth/account/*.json
|
19
27
|
resource :user, path: '', except: [:new, :create]
|
20
28
|
end
|
@@ -5,7 +5,8 @@ module Credible
|
|
5
5
|
|
6
6
|
included do
|
7
7
|
before_action :set_session, only: [:show, :destroy]
|
8
|
-
skip_before_action :authenticate!, only: [:new, :create, :fail]
|
8
|
+
skip_before_action :authenticate!, only: [:new, :create, :refresh, :fail]
|
9
|
+
before_action :authenticate_with_refresh_token!, only: [:refresh]
|
9
10
|
# skip_after_action :verify_authorized, only: [:fail]
|
10
11
|
# TODO: Reevaluate authorization without Pundit
|
11
12
|
end
|
@@ -37,6 +38,19 @@ module Credible
|
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
41
|
+
# POST /refresh
|
42
|
+
# POST /refresh.json
|
43
|
+
def refresh
|
44
|
+
@session = ::Session.new(user: current_user)
|
45
|
+
|
46
|
+
if @session.save
|
47
|
+
current_session.destroy
|
48
|
+
render :show, status: :created, location: @session
|
49
|
+
else
|
50
|
+
render json: @session.errors, status: :unprocessable_entity
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
40
54
|
# DELETE /sessions/1
|
41
55
|
# DELETE /sessions/1.json
|
42
56
|
# DELETE /sessions/current
|
@@ -60,6 +74,10 @@ module Credible
|
|
60
74
|
def session_params
|
61
75
|
params.require(:session).permit(:login, :password)
|
62
76
|
end
|
77
|
+
|
78
|
+
def authenticate_with_refresh_token!
|
79
|
+
warden.authenticate!(:refresh)
|
80
|
+
end
|
63
81
|
end
|
64
82
|
end
|
65
83
|
end
|
data/lib/credible/session.rb
CHANGED
@@ -9,10 +9,22 @@ module Credible
|
|
9
9
|
|
10
10
|
has_secure_token
|
11
11
|
|
12
|
-
def
|
12
|
+
def access_token
|
13
13
|
payload = {
|
14
|
-
data:
|
15
|
-
iss: Rails.application.class.module_parent_name
|
14
|
+
data: access_token_data,
|
15
|
+
iss: Rails.application.class.module_parent_name,
|
16
|
+
iat: Time.now.to_i,
|
17
|
+
exp: Time.now.to_i + 4 * 3600
|
18
|
+
}
|
19
|
+
JWT.encode payload, Rails.application.secrets.secret_key_base, 'HS256' # [1]
|
20
|
+
end
|
21
|
+
|
22
|
+
def refresh_token
|
23
|
+
payload = {
|
24
|
+
data: refresh_token_data,
|
25
|
+
iss: Rails.application.class.module_parent_name,
|
26
|
+
iat: Time.now.to_i,
|
27
|
+
exp: Time.now.to_i + 14 * 24 * 3600
|
16
28
|
}
|
17
29
|
JWT.encode payload, Rails.application.secrets.secret_key_base, 'HS256' # [1]
|
18
30
|
end
|
@@ -27,7 +39,7 @@ module Credible
|
|
27
39
|
|
28
40
|
private
|
29
41
|
|
30
|
-
def
|
42
|
+
def access_token_data
|
31
43
|
{
|
32
44
|
session_id: id,
|
33
45
|
user_id: user.id,
|
@@ -37,6 +49,12 @@ module Credible
|
|
37
49
|
}
|
38
50
|
}
|
39
51
|
end
|
52
|
+
|
53
|
+
def refresh_token_data
|
54
|
+
{
|
55
|
+
session_id: id
|
56
|
+
}
|
57
|
+
end
|
40
58
|
end
|
41
59
|
end
|
42
60
|
|
data/lib/credible/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: credible
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thom Bruce
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|