authorio 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +99 -0
- data/Rakefile +20 -0
- data/app/assets/config/authorio_manifest.js +1 -0
- data/app/assets/stylesheets/authorio/application.css +15 -0
- data/app/assets/stylesheets/authorio/auth.css +41 -0
- data/app/controllers/authorio/application_controller.rb +4 -0
- data/app/controllers/authorio/auth_controller.rb +134 -0
- data/app/controllers/authorio/helpers.rb +17 -0
- data/app/helpers/authorio/application_helper.rb +4 -0
- data/app/helpers/authorio/test_helper.rb +4 -0
- data/app/jobs/authorio/application_job.rb +4 -0
- data/app/models/authorio/application_record.rb +5 -0
- data/app/models/authorio/request.rb +7 -0
- data/app/models/authorio/token.rb +8 -0
- data/app/models/authorio/user.rb +5 -0
- data/app/views/authorio/auth/authorization_interface.html.erb +37 -0
- data/app/views/layouts/authorio/application.html.erb +15 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20210627230156_create_authorio_users.rb +11 -0
- data/db/migrate/20210627230416_create_authorio_requests.rb +13 -0
- data/db/migrate/20210707230416_create_authorio_tokens.rb +13 -0
- data/lib/authorio.rb +27 -0
- data/lib/authorio/configuration.rb +12 -0
- data/lib/authorio/engine.rb +14 -0
- data/lib/authorio/exceptions.rb +5 -0
- data/lib/authorio/routes.rb +9 -0
- data/lib/authorio/version.rb +3 -0
- data/lib/generators/authorio/install/install_generator.rb +17 -0
- data/lib/generators/authorio/install/templates/authorio.rb +15 -0
- data/lib/tasks/authorio_tasks.rake +18 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9a376e3f8c81fdc53ac6c223c42fedadb43cdc02129713ca6756db1506c07f10
|
4
|
+
data.tar.gz: 761c806afafae95a35e97e97b784ae4271cc09fb7cbb6eb6001571e9319cc6a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 32c86c4be9a8cf949ba616797d0a7b505213687d09435ae7c8e0a5588224076c73b0aab4e7b985af74baa89963dafabdc2db7f562982165886dc8085e2fd88c7
|
7
|
+
data.tar.gz: c9bbaf3bce9c291ddf5619a62caa03962d31c1e57abf0fe45baae96d2325cbd1f0d46f1d6c5477fb9cef6dafa9eb54f4ee2874820e8e74b662dd7e8c9d6aa77d
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2021 Michael Meckler
|
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,99 @@
|
|
1
|
+
# Authorio
|
2
|
+
The Authorio plugin turns any Rails-based site into an authentication endpoint for Indieauth.
|
3
|
+
|
4
|
+
## Motivation
|
5
|
+
[IndieAuth](https://indieauth.com/faq) is an authentication protocol that allows you to sign in to a website using a domain name (assuming the web site supports IndieAuth). There are two servers involved in the transaction: the *client*, which is where you're logging in to (authenticating with), and the *authentication endpoint*, which verifies you are who you say you are.
|
6
|
+
|
7
|
+
There are several implementations for IndieAuth clients, if you want to support IndieAuth login on your site. But there aren't many useful implementations of the authentication endpoint. Many people work around this by using an IndieAuth service, such as [RelMeAuth](https://indieweb.org/RelMeAuth) which delegates authentication to a third-party site such as Twitter or Facebook.
|
8
|
+
|
9
|
+
Authorio allows you to create a truly federated authentication setup, using your own Rails site. By adding Authorio to your site, you can remove any external authentication dependencies and log in using only servies you control.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
### 1. Add the Authorio Gem to your bundle
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'authorio'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
```bash
|
22
|
+
$ bundle
|
23
|
+
```
|
24
|
+
|
25
|
+
### 2. Install Authorio config files
|
26
|
+
```bash
|
27
|
+
$ rails generate authorio:install
|
28
|
+
```
|
29
|
+
|
30
|
+
### 3. Install Authorio migrations
|
31
|
+
Authorio needs to add a couple tables to your app's database in order to store (hashed) passwords and access tokens.
|
32
|
+
You will need to install the migrations and then run them to add these tables
|
33
|
+
```bash
|
34
|
+
$ rails authorio:install:migrations
|
35
|
+
Copied migration 20210703002653_create_authorio_users.authorio.rb from authorio
|
36
|
+
Copied migration 20210703002654_create_authorio_requests.authorio.rb from authorio
|
37
|
+
$ rails db:migrate
|
38
|
+
...
|
39
|
+
== 20210703002653 CreateAuthorioUsers: migrated (0.0038s) =====================
|
40
|
+
...
|
41
|
+
== 20210703002654 CreateAuthorioRequests: migrated (0.0041s) ==================
|
42
|
+
```
|
43
|
+
|
44
|
+
### 4. Install Authorio routes
|
45
|
+
Add the following line somewhere inside the `Rails.application.routes.draw do` block in your `config/routes.rb` file
|
46
|
+
```ruby
|
47
|
+
authorio_routes
|
48
|
+
```
|
49
|
+
|
50
|
+
### 5. Add the Indieauth tags
|
51
|
+
Somewhere on your home page, add the following to your view template:
|
52
|
+
```erb
|
53
|
+
<%= indieauth_tag %>
|
54
|
+
```
|
55
|
+
|
56
|
+
This part of the protocol will tell the IndieAuth client where to redirect for authentication. Note that ideally
|
57
|
+
you should only place this tag on your home page, and not in a layout that will put it on every page on your site.
|
58
|
+
(It won't hurt anything but it's redundant to have it in multiple locations)
|
59
|
+
|
60
|
+
### 6. Set your initial password
|
61
|
+
By default, Authorio uses a simple password to authenticate you. This password is hashed and stored in your app
|
62
|
+
database, which presumably you control.
|
63
|
+
|
64
|
+
You are free to customize Authorio to change its authentication scheme however you want, but to get started
|
65
|
+
quickly you'll want to set up a password for yourself.
|
66
|
+
|
67
|
+
```bash
|
68
|
+
$ rake authorio:password
|
69
|
+
|
70
|
+
Enter new password:
|
71
|
+
Confirm password:
|
72
|
+
Password set
|
73
|
+
```
|
74
|
+
|
75
|
+
### 7. Precompile assets
|
76
|
+
|
77
|
+
Authorio has some of its own assets which, if you're running in a production environment, will need to be precompiled
|
78
|
+
like your existing assets. Re-run your normal precompilation step to ensure Authorio's assets are in your asset pipeline
|
79
|
+
```bash
|
80
|
+
$ rails assets:precompile
|
81
|
+
```
|
82
|
+
Now restart your rails app, and you should be all set!
|
83
|
+
|
84
|
+
## Usage
|
85
|
+
|
86
|
+
To test your authentication endpoint, find an IndieAuth client you can log in to. A simple test is at [Pin13](pin13.net/login). Enter your site's URL and click Sign In.
|
87
|
+
|
88
|
+
You should be then be redirected back to your own site and the Authorio
|
89
|
+
login UI
|
90
|
+
<img src="./auth-ui.png" width="400">
|
91
|
+
|
92
|
+
Enter the password you set up when you installed Authorio. This should redirect you back to the client where you
|
93
|
+
will be logged in!
|
94
|
+
|
95
|
+
## Contributing
|
96
|
+
Send pull requests to [Authorio on GitHub](https://github.com/reiterate-app/authorio)
|
97
|
+
|
98
|
+
## License
|
99
|
+
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,20 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
4
|
+
load "rails/tasks/engine.rake"
|
5
|
+
|
6
|
+
load "rails/tasks/statistics.rake"
|
7
|
+
|
8
|
+
load "lib/tasks/authorio_tasks.rake"
|
9
|
+
|
10
|
+
require "bundler/gem_tasks"
|
11
|
+
|
12
|
+
require "rake/testtask"
|
13
|
+
|
14
|
+
Rake::TestTask.new(:test) do |t|
|
15
|
+
t.libs << 'test'
|
16
|
+
t.pattern = 'test/**/*_test.rb'
|
17
|
+
t.verbose = false
|
18
|
+
end
|
19
|
+
|
20
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/authorio .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,41 @@
|
|
1
|
+
div.authorio-auth {
|
2
|
+
padding-top: 200px;
|
3
|
+
}
|
4
|
+
|
5
|
+
.authorio-auth h3 {
|
6
|
+
text-align: center;
|
7
|
+
}
|
8
|
+
|
9
|
+
.authorio-auth .client-row {
|
10
|
+
text-align: center;
|
11
|
+
color: darkolivegreen;
|
12
|
+
margin-top: -0.5em;
|
13
|
+
}
|
14
|
+
|
15
|
+
.authorio-auth span.client {
|
16
|
+
font-weight: bold;
|
17
|
+
}
|
18
|
+
|
19
|
+
.auth-panel {
|
20
|
+
background-color: gainsboro;
|
21
|
+
border-bottom: 2px solid darkgray;
|
22
|
+
padding-bottom: 3em;
|
23
|
+
}
|
24
|
+
|
25
|
+
.authorio-auth label {
|
26
|
+
display: block;
|
27
|
+
margin-left: 1.2em;
|
28
|
+
}
|
29
|
+
|
30
|
+
.authorio-auth input {
|
31
|
+
margin: 0 1em 1em 1em;
|
32
|
+
width: 90%;
|
33
|
+
}
|
34
|
+
|
35
|
+
.authorio-auth form {
|
36
|
+
margin-top: 2em;
|
37
|
+
}
|
38
|
+
|
39
|
+
.authorio-auth input.btn {
|
40
|
+
margin-top: 2em;
|
41
|
+
}
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Authorio
|
2
|
+
class AuthController < ActionController::Base
|
3
|
+
require 'uri'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
protect_from_forgery except: [:send_profile, :issue_token, :authorize_user]
|
7
|
+
|
8
|
+
def authorization_interface
|
9
|
+
p = auth_req_params
|
10
|
+
|
11
|
+
path = if p[:me]
|
12
|
+
URI(p[:me]).path
|
13
|
+
else
|
14
|
+
'/'
|
15
|
+
end
|
16
|
+
|
17
|
+
user = User.find_by! profile_path: path
|
18
|
+
@user_url = p[:me] || user_url(user)
|
19
|
+
|
20
|
+
# If there are any old requests from this (client, user), delete them now
|
21
|
+
Request.where(authorio_user: user, client: p[:client_id]).delete_all
|
22
|
+
|
23
|
+
auth_request = Request.new.tap do |req|
|
24
|
+
req.code = SecureRandom.hex(20)
|
25
|
+
req.redirect_uri = p[:redirect_uri]
|
26
|
+
req.client = p[:client_id] # IndieAuth client_id conflicts with Rails' _id foreign key convention
|
27
|
+
req.scope = p[:scope]
|
28
|
+
req.authorio_user = user
|
29
|
+
end
|
30
|
+
auth_request.save
|
31
|
+
session[:state] = p[:state]
|
32
|
+
session[:code_challenge] = p[:code_challenge]
|
33
|
+
end
|
34
|
+
|
35
|
+
def authorize_user
|
36
|
+
p = auth_user_params
|
37
|
+
user = User.find_by! profile_path: URI(p[:url]).path
|
38
|
+
auth_req = Request.find_by! client: p[:client], authorio_user: user
|
39
|
+
if user.authenticate(p[:password])
|
40
|
+
params = { code: auth_req.code, state: session[:state] }
|
41
|
+
redirect_to "#{auth_req.redirect_uri}?#{params.to_query}"
|
42
|
+
else
|
43
|
+
flash.now[:alert] = "Incorrect password. Try again."
|
44
|
+
redirect_back fallback_location: Authorio.authorization_path, allow_other_host: false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def send_profile
|
49
|
+
begin
|
50
|
+
render json: { 'me': user_url(validate_request.authorio_user) }
|
51
|
+
rescue Authorio::Exceptions::InvalidGrant
|
52
|
+
render invalid_grant
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def issue_token
|
57
|
+
begin
|
58
|
+
req = validate_request
|
59
|
+
raise Authorio::Exceptions::InvalidGrant.new if req.scope.blank?
|
60
|
+
token = Token.create(authorio_user: req.authorio_user, scope: req.scope, client: req.client)
|
61
|
+
render json: {
|
62
|
+
'me': user_url(req.authorio_user),
|
63
|
+
'access_token': token.auth_token,
|
64
|
+
'scope': req.scope,
|
65
|
+
'token_type': 'Bearer'
|
66
|
+
}
|
67
|
+
rescue Authorio::Exceptions::InvalidGrant
|
68
|
+
render invalid_grant
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def verify_token
|
73
|
+
token = Token.find_by auth_token: bearer_token
|
74
|
+
head :bad_request and return if token.nil?
|
75
|
+
render json: {
|
76
|
+
'me': user_url(token.authorio_user),
|
77
|
+
'client_id': token.client,
|
78
|
+
'scope': 'token.scope'
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def auth_req_params
|
85
|
+
%w(client_id redirect_uri state code_challenge).each do |param|
|
86
|
+
unless params.key?(param) && !params[param].empty?
|
87
|
+
raise ::ActionController::ParameterMissing.new(param)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
params.permit(:response_type, :code_challenge, :code_challenge_method, :scope, :me, :redirect_uri, :client_id, :state)
|
91
|
+
end
|
92
|
+
|
93
|
+
def auth_user_params
|
94
|
+
params.permit(:password, :url, :client)
|
95
|
+
end
|
96
|
+
|
97
|
+
def user_url(user)
|
98
|
+
"#{request.scheme}://#{request.host}#{user.profile_path}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def invalid_grant
|
102
|
+
{ json: { 'error': 'invalid_grant' }, status: :bad_request }
|
103
|
+
end
|
104
|
+
|
105
|
+
def code_challenge_failed?
|
106
|
+
# For now, if original request did not have code challenge, then we pass by default
|
107
|
+
return false if session[:code_challenge].nil?
|
108
|
+
sha256 = Digest::SHA256.hexdigest params[:code_verifier]
|
109
|
+
base64 = Base64.urlsafe_encode64 sha256
|
110
|
+
return base64 != session[:code_challenge]
|
111
|
+
end
|
112
|
+
|
113
|
+
def invalid_request?(req)
|
114
|
+
req.redirect_uri != params[:redirect_uri] \
|
115
|
+
|| req.client != params[:client_id] \
|
116
|
+
|| req.created_at < Time.now - 10.minutes
|
117
|
+
end
|
118
|
+
|
119
|
+
def validate_request
|
120
|
+
req = Request.find_by code: params[:code]
|
121
|
+
raise Authorio::Exceptions::InvalidGrant.new if req.nil?
|
122
|
+
req.delete
|
123
|
+
raise Authorio::Exceptions::InvalidGrant.new if invalid_request?(req) || code_challenge_failed?
|
124
|
+
req
|
125
|
+
end
|
126
|
+
|
127
|
+
def bearer_token
|
128
|
+
bearer = /^Bearer /
|
129
|
+
header = request.headers['Authorization']
|
130
|
+
header.gsub(bearer, '') if header && header.match(bearer)
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Authorio
|
2
|
+
# These helpers are provided to the main application
|
3
|
+
module Helpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
if respond_to?(:helper_method)
|
8
|
+
helper_method :indieauth_tag
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def indieauth_tag
|
13
|
+
%Q[<link rel="authorization_endpoint" href="#{URI.join(root_url, Authorio.authorization_path)}">
|
14
|
+
<link rel="token_endpoint" href="#{URI.join(root_url, Authorio.token_path)}">].html_safe
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en-GB">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>Authorio Login</title>
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
<link rel="stylesheet"
|
8
|
+
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
|
9
|
+
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
|
10
|
+
crossorigin="anonymous">
|
11
|
+
<%= stylesheet_link_tag "authorio/auth" %>
|
12
|
+
</head>
|
13
|
+
<body>
|
14
|
+
<div class="container authorio-auth">
|
15
|
+
<div class="row">
|
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) %>
|
26
|
+
<%= form.label(:password, "Password") %>
|
27
|
+
<%= form.password_field(:password) %>
|
28
|
+
<%= form.hidden_field(:client, value: params[:client_id]) %>
|
29
|
+
<%= form.submit("Sign in", class: 'btn btn-success') %>
|
30
|
+
<% end %>
|
31
|
+
</div>
|
32
|
+
<div class="col-md-4">
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</body>
|
37
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Authorio::Engine.routes.draw do
|
2
|
+
get Authorio.configuration.authorization_endpoint, controller: 'auth', action: 'authorization_interface'
|
3
|
+
post Authorio.configuration.authorization_endpoint, controller: 'auth', action: 'send_profile'
|
4
|
+
post '/authorize_user', controller: 'auth', action: 'authorize_user'
|
5
|
+
get Authorio.configuration.token_endpoint, controller: 'auth', action: 'verify_token'
|
6
|
+
post Authorio.configuration.token_endpoint, controller: 'auth', action: 'issue_token'
|
7
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateAuthorioRequests < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
create_table :authorio_requests do |t|
|
4
|
+
t.string :code
|
5
|
+
t.string :redirect_uri
|
6
|
+
t.string :client
|
7
|
+
t.string :scope
|
8
|
+
t.references :authorio_user, null: false, foreign_key: true
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateAuthorioTokens < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
create_table :authorio_tokens do |t|
|
4
|
+
t.string :client
|
5
|
+
t.string :scope
|
6
|
+
t.references :authorio_user, null: false, foreign_key: true
|
7
|
+
t.string :auth_token
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
add_index :authorio_tokens, :auth_token, unique: true
|
12
|
+
end
|
13
|
+
end
|
data/lib/authorio.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "authorio/version"
|
2
|
+
require "authorio/engine"
|
3
|
+
require "authorio/configuration"
|
4
|
+
require "authorio/routes"
|
5
|
+
require "authorio/exceptions"
|
6
|
+
|
7
|
+
module Authorio
|
8
|
+
class << self
|
9
|
+
attr_accessor :configuration, :authorization_path
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.configuration
|
13
|
+
@configuration ||= Configuration.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure
|
17
|
+
yield configuration
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.authorization_path
|
21
|
+
return [Authorio.configuration.mount_point, Authorio.configuration.authorization_endpoint].join("/")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.token_path
|
25
|
+
return [Authorio.configuration.mount_point, Authorio.configuration.token_endpoint].join("/")
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Authorio
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace Authorio
|
4
|
+
|
5
|
+
initializer "authorio.load_helpers" do |app|
|
6
|
+
ActionController::Base.send :include, Authorio::Helpers
|
7
|
+
end
|
8
|
+
|
9
|
+
initializer "authorio.assets.precompile" do |app|
|
10
|
+
app.config.assets.precompile += %w( authorio/auth.css )
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Authorio
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
3
|
+
|
4
|
+
def self.source_paths
|
5
|
+
paths = []
|
6
|
+
paths << File.expand_path('../templates', "../../#{__FILE__}")
|
7
|
+
paths << File.expand_path('../templates', "../#{__FILE__}")
|
8
|
+
paths << File.expand_path('../templates', __FILE__)
|
9
|
+
paths.flatten
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_files
|
13
|
+
template 'authorio.rb', 'config/initializers/authorio.rb'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Configuration for Authorio IndieAuth authentication
|
2
|
+
|
3
|
+
Authorio.configure do |config|
|
4
|
+
|
5
|
+
# Mount point for Authorio URLs. Typically you would call this in your routes.rb
|
6
|
+
# as mount Authorio::Engine, at: mount_point
|
7
|
+
# But Authorio needs to know its own mount point, so we define it here and use a custom mount command in the config
|
8
|
+
# config.mount_point = "authorio"
|
9
|
+
|
10
|
+
# The path where clients will be redirected to provide authentication
|
11
|
+
# config.authorization_endpoint = "auth"
|
12
|
+
|
13
|
+
# The path for token requests
|
14
|
+
# config.token_endpoint = "token"
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
namespace :authorio do
|
2
|
+
desc "Set password for initial Authorio user"
|
3
|
+
require 'io/console'
|
4
|
+
|
5
|
+
def input_no_echo(prompt)
|
6
|
+
print("\n#{prompt}")
|
7
|
+
STDIN.noecho(&:gets).chop
|
8
|
+
end
|
9
|
+
|
10
|
+
task :password => :environment do
|
11
|
+
passwd = input_no_echo("Enter new password: ")
|
12
|
+
passwd_confirm = input_no_echo("Confirm password: ")
|
13
|
+
user = Authorio::User.
|
14
|
+
create_with(password: passwd, password_confirmation:passwd_confirm).
|
15
|
+
find_or_create_by!(profile_path: '/')
|
16
|
+
puts("\nPassword set")
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: authorio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Meckler
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-11 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.3
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 6.1.3.2
|
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.3
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 6.1.3.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bcrypt
|
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: factory_bot_rails
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
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: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec-rails
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: byebug
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
description: Rails engine to add IndieAuth authentication endpoiont functionality
|
104
|
+
email:
|
105
|
+
- rattroupe@reiterate-app.com
|
106
|
+
executables: []
|
107
|
+
extensions: []
|
108
|
+
extra_rdoc_files: []
|
109
|
+
files:
|
110
|
+
- MIT-LICENSE
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- app/assets/config/authorio_manifest.js
|
114
|
+
- app/assets/stylesheets/authorio/application.css
|
115
|
+
- app/assets/stylesheets/authorio/auth.css
|
116
|
+
- app/controllers/authorio/application_controller.rb
|
117
|
+
- app/controllers/authorio/auth_controller.rb
|
118
|
+
- app/controllers/authorio/helpers.rb
|
119
|
+
- app/helpers/authorio/application_helper.rb
|
120
|
+
- app/helpers/authorio/test_helper.rb
|
121
|
+
- app/jobs/authorio/application_job.rb
|
122
|
+
- app/models/authorio/application_record.rb
|
123
|
+
- app/models/authorio/request.rb
|
124
|
+
- app/models/authorio/token.rb
|
125
|
+
- app/models/authorio/user.rb
|
126
|
+
- app/views/authorio/auth/authorization_interface.html.erb
|
127
|
+
- app/views/layouts/authorio/application.html.erb
|
128
|
+
- config/routes.rb
|
129
|
+
- db/migrate/20210627230156_create_authorio_users.rb
|
130
|
+
- db/migrate/20210627230416_create_authorio_requests.rb
|
131
|
+
- db/migrate/20210707230416_create_authorio_tokens.rb
|
132
|
+
- lib/authorio.rb
|
133
|
+
- lib/authorio/configuration.rb
|
134
|
+
- lib/authorio/engine.rb
|
135
|
+
- lib/authorio/exceptions.rb
|
136
|
+
- lib/authorio/routes.rb
|
137
|
+
- lib/authorio/version.rb
|
138
|
+
- lib/generators/authorio/install/install_generator.rb
|
139
|
+
- lib/generators/authorio/install/templates/authorio.rb
|
140
|
+
- lib/tasks/authorio_tasks.rake
|
141
|
+
homepage: https://rubygems.org/gems/authorio
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata:
|
145
|
+
homepage_uri: https://rubygems.org/gems/authorio
|
146
|
+
source_code_uri: https://github.com/reiterate-app/authorio
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
require_paths:
|
150
|
+
- lib
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
requirements: []
|
162
|
+
rubygems_version: 3.2.11
|
163
|
+
signing_key:
|
164
|
+
specification_version: 4
|
165
|
+
summary: Indieauth Authentication endpoint for Rails
|
166
|
+
test_files: []
|