authorio 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -0
- data/app/assets/stylesheets/authorio/auth.css +23 -1
- data/app/controllers/authorio/auth_controller.rb +87 -44
- data/app/{controllers/authorio/helpers.rb → helpers/authorio/tag_helper.rb} +3 -3
- data/app/models/authorio/session.rb +40 -0
- data/app/models/authorio/token.rb +8 -0
- data/app/views/authorio/auth/authorization_interface.html.erb +28 -32
- data/app/views/layouts/authorio/main.html.erb +27 -0
- data/config/routes.rb +3 -1
- data/db/migrate/20210723161041_add_expiry_to_tokens.rb +5 -0
- data/db/migrate/20210726164625_create_authorio_sessions.rb +12 -0
- data/lib/authorio/configuration.rb +4 -1
- data/lib/authorio/engine.rb +5 -4
- data/lib/authorio/exceptions.rb +9 -0
- data/lib/authorio/version.rb +1 -1
- data/lib/generators/authorio/install/templates/authorio.rb +9 -0
- metadata +18 -19
- data/app/controllers/authorio/application_controller.rb +0 -4
- data/app/helpers/authorio/application_helper.rb +0 -4
- data/app/helpers/authorio/test_helper.rb +0 -4
- data/app/views/layouts/authorio/application.html.erb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b69bae6ee41c0e027922f5bc07b2bc61c72c86026a8e42eee97366453858af43
|
4
|
+
data.tar.gz: 496cb0ada5d2802e789b34e28ed21dc320b4ce76c9b9036b705ea8f7219efa8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a361fbec959948621257d111de2af8256fc23fee38be56660c66b5b68b8f80972660317ac06d997c93cd28b62406387089a67110894d09acdf34d60e2b8635c
|
7
|
+
data.tar.gz: a887161dd53aedea2527d1678db6fc6cd7c7d22aff6631442cde63d61d4f6093f29c08bcab8ef20c278d255e247eb5fcb8c5be549ced931f81ac2954e8d1c7fe
|
data/README.md
CHANGED
@@ -106,6 +106,31 @@ will be logged in!
|
|
106
106
|
When you installed Authorio it placed a config file in `config/initializers/authorio.rb`. If you want to change
|
107
107
|
one of the defaults you can uncomment it and specify it here.
|
108
108
|
|
109
|
+
### Mount Point
|
110
|
+
|
111
|
+
Most Rails engines are mounted via `mount Authorio::Engine, at: mount_point`. But Authorio needs to know its own
|
112
|
+
mount point (to specify its url in the header tag) so you specify the mount point here. The default `authorio`
|
113
|
+
should work for everyone.
|
114
|
+
|
115
|
+
### Authorization and Token Endpoint
|
116
|
+
|
117
|
+
These endpointd are given to servers via discovery. The default values should suffice.
|
118
|
+
|
119
|
+
### Token Expiration
|
120
|
+
|
121
|
+
If a client asks for an authentication token, the token will be valid for this length of time, after which
|
122
|
+
you will have to re-authenticate. Longer-lasting
|
123
|
+
tokens can possibly be a security risk. Default is 4 weeks.
|
124
|
+
|
125
|
+
### Local Session Lifetime
|
126
|
+
|
127
|
+
Setting this to a time interval will enable you to authenticate without typing in your password. It enables a
|
128
|
+
"remember me" chekbox on the authentication form. If you check that, then enter your
|
129
|
+
password once, then your session will be saved in a cookie, and any time you are asked to authenticate again,
|
130
|
+
you can just click "Sign In" without your password. It can be a security risk if someone else has access to
|
131
|
+
the machine you are using to login with (eg your laptop). Obviously you don't want to check "remember me"
|
132
|
+
on a public-access computer. Default is *nil* (disabled)
|
133
|
+
|
109
134
|
### TODO
|
110
135
|
|
111
136
|
- [ ] Customizing the authentication view/UI
|
@@ -27,7 +27,7 @@ div.authorio-auth {
|
|
27
27
|
margin-left: 1.2em;
|
28
28
|
}
|
29
29
|
|
30
|
-
.authorio-auth input {
|
30
|
+
.authorio-auth input:not([type='checkbox']):not([type='submit']) {
|
31
31
|
margin: 0 1em 1em 1em;
|
32
32
|
width: 90%;
|
33
33
|
}
|
@@ -39,3 +39,25 @@ div.authorio-auth {
|
|
39
39
|
.authorio-auth input.btn {
|
40
40
|
margin-top: 2em;
|
41
41
|
}
|
42
|
+
|
43
|
+
.auth-btn-row {
|
44
|
+
margin: 1em;
|
45
|
+
width: 90%;
|
46
|
+
}
|
47
|
+
|
48
|
+
.authorio-auth .auth-btn-row .auth-btn {
|
49
|
+
width: 45%;
|
50
|
+
margin: 0.1em;
|
51
|
+
}
|
52
|
+
|
53
|
+
.authorio-auth .auth-btn-row .auth-btn:last-child {
|
54
|
+
float: right;
|
55
|
+
}
|
56
|
+
|
57
|
+
span.r-m {
|
58
|
+
font-weight: 200;
|
59
|
+
}
|
60
|
+
|
61
|
+
label.remember {
|
62
|
+
margin-top: -1em;
|
63
|
+
}
|
@@ -2,84 +2,103 @@ module Authorio
|
|
2
2
|
class AuthController < ActionController::Base
|
3
3
|
require 'uri'
|
4
4
|
require 'digest'
|
5
|
+
layout 'authorio/main'
|
5
6
|
|
6
|
-
|
7
|
+
# These API-only endpoints are protected by code challenge and do not need CSRF protextion
|
8
|
+
protect_from_forgery with: :exception, except: [:send_profile, :issue_token]
|
9
|
+
|
10
|
+
rescue_from 'Authorio::Exceptions::SessionReplayAttack' do |exception|
|
11
|
+
redirect_back_with_error "Session Replay attack detected. This has been logged."
|
12
|
+
logger.info "Session replay attack detected!"
|
13
|
+
Authorio::Session.where(user: exception.session.user).delete_all
|
14
|
+
end
|
7
15
|
|
8
16
|
def authorization_interface
|
9
17
|
p = auth_req_params
|
10
18
|
p[:me] ||= "#{host_with_protocol}/"
|
11
|
-
|
12
|
-
user = User.find_by! profile_path: URI(p[:me]).path
|
13
|
-
@user_url = p[:me] || user_url(user)
|
19
|
+
@user = User.find_by! profile_path: URI(p[:me]).path
|
14
20
|
|
15
21
|
# If there are any old requests from this (client, user), delete them now
|
16
|
-
Request.where(authorio_user: user, client: p[:client_id]).delete_all
|
22
|
+
Request.where(authorio_user: @user, client: p[:client_id]).delete_all
|
17
23
|
|
18
24
|
auth_request = Request.new.tap do |req|
|
19
25
|
req.code = SecureRandom.hex(20)
|
20
26
|
req.redirect_uri = p[:redirect_uri]
|
21
27
|
req.client = p[:client_id] # IndieAuth client_id conflicts with Rails' _id foreign key convention
|
22
28
|
req.scope = p[:scope]
|
23
|
-
req.authorio_user = user
|
29
|
+
req.authorio_user = @user
|
24
30
|
end
|
25
31
|
auth_request.save
|
26
32
|
session[:state] = p[:state]
|
27
33
|
session[:code_challenge] = p[:code_challenge]
|
34
|
+
session[:client_id] = p[:client_id]
|
35
|
+
@user_logged_in_locally = !user_session.nil?
|
36
|
+
@rememberable = Authorio.configuration.local_session_lifetime && !@user_logged_in_locally
|
28
37
|
|
29
38
|
rescue ActiveRecord::RecordNotFound
|
30
|
-
|
31
|
-
redirect_back fallback_location: Authorio.authorization_path, allow_other_host: false
|
39
|
+
redirect_back_with_error "Invalid user"
|
32
40
|
end
|
33
41
|
|
34
42
|
def authorize_user
|
35
43
|
p = auth_user_params
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
+
|
45
|
+
if params[:commit] == "Cancel"
|
46
|
+
redirect_to session[:client_id] and return
|
47
|
+
end
|
48
|
+
|
49
|
+
user = authenticate_user_from_session_or_password
|
50
|
+
if p[:remember_me]
|
51
|
+
cookies.encrypted[:user] = {
|
52
|
+
value: Authorio::Session.create(authorio_user: user).as_cookie,
|
53
|
+
expires: Authorio.configuration.local_session_lifetime
|
54
|
+
}
|
44
55
|
end
|
56
|
+
|
57
|
+
auth_req = Request.find_by! client: session[:client_id], authorio_user: user
|
58
|
+
params = { code: auth_req.code, state: session[:state] }
|
59
|
+
redirect_to "#{auth_req.redirect_uri}?#{params.to_query}"
|
60
|
+
|
45
61
|
rescue ActiveRecord::RecordNotFound
|
46
|
-
|
47
|
-
|
62
|
+
redirect_back_with_error "Invalid user"
|
63
|
+
rescue Authorio::Exceptions::InvalidPassword
|
64
|
+
redirect_back_with_error "Incorrect password. Try again."
|
48
65
|
end
|
49
66
|
|
50
67
|
def send_profile
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
render invalid_grant
|
55
|
-
end
|
68
|
+
render json: { 'me': user_url(validate_request.authorio_user) }
|
69
|
+
rescue Authorio::Exceptions::InvalidGrant
|
70
|
+
render invalid_grant
|
56
71
|
end
|
57
72
|
|
58
73
|
def issue_token
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
74
|
+
req = validate_request
|
75
|
+
raise Authorio::Exceptions::InvalidGrant.new if req.scope.blank?
|
76
|
+
token = Token.create(authorio_user: req.authorio_user, scope: req.scope, client: req.client)
|
77
|
+
render json: {
|
78
|
+
'me': user_url(req.authorio_user),
|
79
|
+
'access_token': token.auth_token,
|
80
|
+
'scope': req.scope,
|
81
|
+
'expires_in': Authorio.configuration.token_expiration,
|
82
|
+
'token_type': 'Bearer'
|
83
|
+
}
|
84
|
+
rescue Authorio::Exceptions::InvalidGrant
|
85
|
+
render invalid_grant
|
72
86
|
end
|
73
87
|
|
74
88
|
def verify_token
|
75
89
|
token = Token.find_by! auth_token: bearer_token
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
90
|
+
if token.expired?
|
91
|
+
token.delete
|
92
|
+
render token_expired
|
93
|
+
else
|
94
|
+
render json: {
|
95
|
+
'me': user_url(token.authorio_user),
|
96
|
+
'client_id': token.client,
|
97
|
+
'scope': 'token.scope'
|
98
|
+
}
|
99
|
+
end
|
100
|
+
rescue ActiveRecord::RecordNotFound
|
101
|
+
head :bad_request
|
83
102
|
end
|
84
103
|
|
85
104
|
private
|
@@ -94,7 +113,7 @@ module Authorio
|
|
94
113
|
end
|
95
114
|
|
96
115
|
def auth_user_params
|
97
|
-
params.permit(:password, :url, :
|
116
|
+
params.require(:user).permit(:password, :url, :remember_me)
|
98
117
|
end
|
99
118
|
|
100
119
|
def host_with_protocol
|
@@ -109,6 +128,10 @@ module Authorio
|
|
109
128
|
{ json: { 'error': 'invalid_grant' }, status: :bad_request }
|
110
129
|
end
|
111
130
|
|
131
|
+
def token_expired
|
132
|
+
{ json: {'error': 'invalid_token', 'error_message': 'The access token has expired' }, status: :unauthorized }
|
133
|
+
end
|
134
|
+
|
112
135
|
def code_challenge_failed?
|
113
136
|
# For now, if original request did not have code challenge, then we pass by default
|
114
137
|
return false if session[:code_challenge].nil?
|
@@ -137,5 +160,25 @@ module Authorio
|
|
137
160
|
header.gsub(bearer, '') if header && header.match(bearer)
|
138
161
|
end
|
139
162
|
|
163
|
+
def user_session
|
164
|
+
cookie = cookies.encrypted[:user] and Session.find_by_cookie(cookie)
|
165
|
+
end
|
166
|
+
|
167
|
+
def redirect_back_with_error(error)
|
168
|
+
flash[:alert] = error
|
169
|
+
redirect_back fallback_location: Authorio.authorization_path, allow_other_host: false
|
170
|
+
end
|
171
|
+
|
172
|
+
def authenticate_user_from_session_or_password
|
173
|
+
session = user_session
|
174
|
+
if session
|
175
|
+
return session.authorio_user
|
176
|
+
else
|
177
|
+
user = User.find_by! profile_path: URI(auth_user_params[:url]).path
|
178
|
+
raise Authorio::Exceptions::InvalidPassword unless user.authenticate(auth_user_params[:password])
|
179
|
+
return user
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
140
183
|
end
|
141
184
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Authorio
|
2
2
|
# These helpers are provided to the main application
|
3
|
-
module
|
3
|
+
module TagHelper
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
@@ -10,8 +10,8 @@ module Authorio
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def indieauth_tag
|
13
|
-
|
14
|
-
|
13
|
+
tag(:link, rel: 'authorization_endpoint', href: URI.join(root_url, Authorio.authorization_path)) <<
|
14
|
+
tag(:link, rel: 'token_endpoint', href: URI.join(root_url, Authorio.token_path))
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Authorio
|
2
|
+
class Session < ApplicationRecord
|
3
|
+
# Implement a session cookie store based on best security practices
|
4
|
+
# See: https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence
|
5
|
+
belongs_to :authorio_user, class_name: "::Authorio::User"
|
6
|
+
|
7
|
+
# 1. Protect against having database stolen by only storing token hashes
|
8
|
+
attribute :token # This will not be persisted in the DB
|
9
|
+
has_secure_token
|
10
|
+
|
11
|
+
before_create do
|
12
|
+
self.expires_at = Time.now + Authorio.configuration.token_expiration
|
13
|
+
self.selector = SecureRandom.hex(12)
|
14
|
+
self.hashed_token = Digest::SHA256.hexdigest self.token
|
15
|
+
end
|
16
|
+
|
17
|
+
# 2. To guard against timing attacks, we lookup tokens based on a separate selector attribute
|
18
|
+
# and compare them using a secure time-constant comparison method
|
19
|
+
def self.find_by_cookie(cookie)
|
20
|
+
_selector, _token = cookie.split(':')
|
21
|
+
session = find_by selector: _selector
|
22
|
+
raise Authorio::Exceptions::SessionReplayAttack.new(session) unless session.matches_cookie?(cookie)
|
23
|
+
session
|
24
|
+
end
|
25
|
+
|
26
|
+
def matches_cookie?(cookie)
|
27
|
+
_selector, _token = cookie.split(':')
|
28
|
+
_hashed_token = Digest::SHA256.hexdigest _token
|
29
|
+
!expired? && ActiveSupport::SecurityUtils.secure_compare(_hashed_token, hashed_token)
|
30
|
+
end
|
31
|
+
|
32
|
+
def expired?
|
33
|
+
return expires_at < Time.now
|
34
|
+
end
|
35
|
+
|
36
|
+
def as_cookie
|
37
|
+
"#{selector}:#{token}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -4,5 +4,13 @@ module Authorio
|
|
4
4
|
has_secure_token :auth_token
|
5
5
|
|
6
6
|
validates_presence_of :scope, :client
|
7
|
+
|
8
|
+
before_create do
|
9
|
+
self.expires_at = Time.now + Authorio.configuration.token_expiration
|
10
|
+
end
|
11
|
+
|
12
|
+
def expired?
|
13
|
+
return expires_at < Time.now
|
14
|
+
end
|
7
15
|
end
|
8
16
|
end
|
@@ -1,37 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
<
|
7
|
-
<
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
<div class="col-md-4">
|
17
|
-
</div>
|
18
|
-
<div class="col-md-4 auth-panel">
|
19
|
-
<h3>Authorio</h3>
|
20
|
-
<div class="client-row">
|
21
|
-
Authenticating with <span class="client"><%= params[:client_id] %>
|
22
|
-
</div>
|
23
|
-
<%= form_with(url: "authorize_user", method: :post) do |form| %>
|
24
|
-
<%= form.label(:url, "User URL") %>
|
25
|
-
<%= form.text_field(:url, value: @user_url, readonly: true) %>
|
1
|
+
<%= stylesheet_link_tag "authorio/auth" %>
|
2
|
+
<% content_for :title, "Authorio Login" %>
|
3
|
+
|
4
|
+
<div class="container authorio-auth">
|
5
|
+
<div class="row">
|
6
|
+
<div class="col-md-4"></div>
|
7
|
+
<div class="col-md-4 auth-panel">
|
8
|
+
<h3>Authorio</h3>
|
9
|
+
<div class="client-row">
|
10
|
+
Authenticating with <span class="client"><%= params[:client_id] %>
|
11
|
+
</div>
|
12
|
+
<%= form_with(model: @user, url: authorize_user_path(@user), method: :post) do |form| %>
|
13
|
+
<%= form.label(:url, "User URL") %>
|
14
|
+
<%= form.text_field(:url, value: params[:me], readonly: true) %>
|
15
|
+
<% unless @user_logged_in_locally %>
|
26
16
|
<%= form.label(:password, "Password") %>
|
27
17
|
<%= form.password_field(:password, autofocus: true) %>
|
28
|
-
|
29
|
-
|
18
|
+
<% if @rememberable %>
|
19
|
+
<%= label_tag(:remember_me, class: 'remember') do %>
|
20
|
+
<%= form.check_box :remember_me %>
|
21
|
+
<span class='r-m'>Remember me for <%= distance_of_time_in_words Authorio.configuration.local_session_lifetime -%></span>
|
22
|
+
<% end %>
|
30
23
|
<% end %>
|
24
|
+
<% end %>
|
25
|
+
<div class='auth-btn-row'>
|
26
|
+
<%= form.submit("Cancel", class: 'btn btn-default auth-btn') %>
|
27
|
+
<%= form.submit("Sign in", class: 'btn btn-success auth-btn') %>
|
31
28
|
</div>
|
32
|
-
|
33
|
-
</div>
|
34
|
-
</div>
|
29
|
+
<% end %>
|
35
30
|
</div>
|
36
|
-
|
37
|
-
</
|
31
|
+
<div class="col-md-4"></div>
|
32
|
+
</div>
|
33
|
+
</div>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title><%= yield(:title) %></title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
<meta charset="utf-8">
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
9
|
+
<link rel="stylesheet"
|
10
|
+
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
|
11
|
+
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
|
12
|
+
crossorigin="anonymous">
|
13
|
+
|
14
|
+
<%= stylesheet_link_tag "authorio/application", media: "all" %>
|
15
|
+
</head>
|
16
|
+
<body data-no-turbolinks="true" data-turbolinks="false">
|
17
|
+
|
18
|
+
<% flash.each do |key, value| %>
|
19
|
+
<div class="alert alert-warning">
|
20
|
+
<p><%= value %></p>
|
21
|
+
</div>
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<%= yield %>
|
25
|
+
|
26
|
+
</body>
|
27
|
+
</html>
|
data/config/routes.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
Authorio::Engine.routes.draw do
|
2
2
|
get Authorio.configuration.authorization_endpoint, controller: 'auth', action: 'authorization_interface'
|
3
3
|
post Authorio.configuration.authorization_endpoint, controller: 'auth', action: 'send_profile'
|
4
|
-
|
4
|
+
resources :users do
|
5
|
+
post 'authorize', on: :member, to: 'auth#authorize_user'
|
6
|
+
end
|
5
7
|
get Authorio.configuration.token_endpoint, controller: 'auth', action: 'verify_token'
|
6
8
|
post Authorio.configuration.token_endpoint, controller: 'auth', action: 'issue_token'
|
7
9
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateAuthorioSessions < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
create_table :authorio_sessions do |t|
|
4
|
+
t.references :authorio_user, null: false, foreign_key: true
|
5
|
+
t.string :selector
|
6
|
+
t.string :hashed_token
|
7
|
+
t.datetime :expires_at
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module Authorio
|
2
2
|
class Configuration
|
3
3
|
|
4
|
-
attr_accessor :authorization_endpoint, :token_endpoint, :mount_point
|
4
|
+
attr_accessor :authorization_endpoint, :token_endpoint, :mount_point, :token_expiration,
|
5
|
+
:local_session_lifetime
|
5
6
|
|
6
7
|
def initialize
|
7
8
|
@authorization_endpoint = "auth"
|
8
9
|
@token_endpoint = "token"
|
9
10
|
@mount_point = "authorio"
|
11
|
+
@token_expiration = 4.weeks
|
12
|
+
@local_session_lifetime = nil
|
10
13
|
end
|
11
14
|
end
|
12
15
|
end
|
data/lib/authorio/engine.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
module Authorio
|
2
|
-
|
2
|
+
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace Authorio
|
4
4
|
|
5
5
|
initializer "authorio.load_helpers" do |app|
|
6
|
-
|
6
|
+
Rails.application.reloader.to_prepare do
|
7
|
+
ActionView::Base.send :include, Authorio::TagHelper
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
11
|
initializer "authorio.assets.precompile" do |app|
|
10
12
|
app.config.assets.precompile += %w( authorio/auth.css )
|
11
13
|
end
|
12
|
-
|
13
|
-
end
|
14
|
+
end
|
14
15
|
end
|
data/lib/authorio/exceptions.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
module Authorio
|
2
2
|
module Exceptions
|
3
3
|
class InvalidGrant < RuntimeError; end
|
4
|
+
class InvalidPassword < RuntimeError; end
|
5
|
+
|
6
|
+
class SessionReplayAttack < StandardError
|
7
|
+
attr_accessor :session
|
8
|
+
|
9
|
+
def initialize(session)
|
10
|
+
@session = session
|
11
|
+
end
|
12
|
+
end
|
4
13
|
end
|
5
14
|
end
|
data/lib/authorio/version.rb
CHANGED
@@ -12,4 +12,13 @@ Authorio.configure do |config|
|
|
12
12
|
|
13
13
|
# The path for token requests
|
14
14
|
# config.token_endpoint = "token"
|
15
|
+
|
16
|
+
# How long tokens will last before expiring
|
17
|
+
# config.token_expiration = 4.weeks
|
18
|
+
|
19
|
+
# Enable local session lifetime to keep yourself "logged in" to your own server
|
20
|
+
# If set to eg:
|
21
|
+
# config.local_session_lifetime = 30.days
|
22
|
+
# then you will only have to enter your password every 30 days. Default is off (nil)
|
23
|
+
# config.local_session_lifetime = nil
|
15
24
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authorio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Meckler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -34,70 +34,70 @@ dependencies:
|
|
34
34
|
name: bcrypt
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '3.0'
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- - "
|
44
|
+
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '3.0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: factory_bot_rails
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- - "
|
51
|
+
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '6.0'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
|
-
- - "
|
58
|
+
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '6.0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: rspec
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
|
-
- - "
|
65
|
+
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
67
|
version: '3.0'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- - "
|
72
|
+
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '3.0'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: rspec-rails
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
|
-
- - "
|
79
|
+
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '5.0'
|
82
82
|
type: :development
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
|
-
- - "
|
86
|
+
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '5.0'
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
90
|
name: byebug
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
|
-
- - "
|
93
|
+
- - "~>"
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: '11.0'
|
96
96
|
type: :development
|
97
97
|
prerelease: false
|
98
98
|
version_requirements: !ruby/object:Gem::Requirement
|
99
99
|
requirements:
|
100
|
-
- - "
|
100
|
+
- - "~>"
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '11.0'
|
103
103
|
description: Rails engine to add IndieAuth authentication endpoint functionality
|
@@ -113,22 +113,22 @@ files:
|
|
113
113
|
- app/assets/config/authorio_manifest.js
|
114
114
|
- app/assets/stylesheets/authorio/application.css
|
115
115
|
- app/assets/stylesheets/authorio/auth.css
|
116
|
-
- app/controllers/authorio/application_controller.rb
|
117
116
|
- app/controllers/authorio/auth_controller.rb
|
118
|
-
- app/
|
119
|
-
- app/helpers/authorio/application_helper.rb
|
120
|
-
- app/helpers/authorio/test_helper.rb
|
117
|
+
- app/helpers/authorio/tag_helper.rb
|
121
118
|
- app/jobs/authorio/application_job.rb
|
122
119
|
- app/models/authorio/application_record.rb
|
123
120
|
- app/models/authorio/request.rb
|
121
|
+
- app/models/authorio/session.rb
|
124
122
|
- app/models/authorio/token.rb
|
125
123
|
- app/models/authorio/user.rb
|
126
124
|
- app/views/authorio/auth/authorization_interface.html.erb
|
127
|
-
- app/views/layouts/authorio/
|
125
|
+
- app/views/layouts/authorio/main.html.erb
|
128
126
|
- config/routes.rb
|
129
127
|
- db/migrate/20210627230156_create_authorio_users.rb
|
130
128
|
- db/migrate/20210627230416_create_authorio_requests.rb
|
131
129
|
- db/migrate/20210707230416_create_authorio_tokens.rb
|
130
|
+
- db/migrate/20210723161041_add_expiry_to_tokens.rb
|
131
|
+
- db/migrate/20210726164625_create_authorio_sessions.rb
|
132
132
|
- lib/authorio.rb
|
133
133
|
- lib/authorio/configuration.rb
|
134
134
|
- lib/authorio/engine.rb
|
@@ -138,11 +138,10 @@ files:
|
|
138
138
|
- lib/generators/authorio/install/install_generator.rb
|
139
139
|
- lib/generators/authorio/install/templates/authorio.rb
|
140
140
|
- lib/tasks/authorio_tasks.rake
|
141
|
-
homepage:
|
141
|
+
homepage:
|
142
142
|
licenses:
|
143
143
|
- MIT
|
144
144
|
metadata:
|
145
|
-
homepage_uri: https://rubygems.org/gems/authorio
|
146
145
|
source_code_uri: https://github.com/reiterate-app/authorio
|
147
146
|
post_install_message:
|
148
147
|
rdoc_options: []
|