rodauth-oauth 0.1.0 → 0.4.2
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/CHANGELOG.md +108 -0
- data/README.md +2 -1
- data/lib/generators/roda/oauth/templates/db/migrate/create_rodauth_oauth.rb +4 -4
- data/lib/rodauth/features/oauth.rb +461 -355
- data/lib/rodauth/features/oauth_http_mac.rb +6 -12
- data/lib/rodauth/features/oauth_jwt.rb +70 -52
- data/lib/rodauth/features/oauth_saml.rb +104 -0
- data/lib/rodauth/features/oidc.rb +217 -85
- data/lib/rodauth/oauth/database_extensions.rb +73 -0
- data/lib/rodauth/oauth/ttl_store.rb +1 -1
- data/lib/rodauth/oauth/version.rb +1 -1
- data/templates/authorize.str +34 -0
- data/templates/client_secret_field.str +4 -0
- data/templates/description_field.str +4 -0
- data/templates/homepage_url_field.str +4 -0
- data/templates/name_field.str +4 -0
- data/templates/new_oauth_application.str +10 -0
- data/templates/oauth_application.str +11 -0
- data/templates/oauth_applications.str +14 -0
- data/templates/oauth_tokens.str +49 -0
- data/templates/redirect_uri_field.str +4 -0
- data/templates/scope_field.str +10 -0
- metadata +20 -7
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
module OAuth
|
5
|
+
# rubocop:disable Naming/MethodName, Metrics/ParameterLists
|
6
|
+
def self.ExtendDatabase(db)
|
7
|
+
Module.new do
|
8
|
+
dataset = db.dataset
|
9
|
+
|
10
|
+
if dataset.supports_returning?(:insert)
|
11
|
+
def __insert_and_return__(dataset, _pkey, params)
|
12
|
+
dataset.returning.insert(params).first
|
13
|
+
end
|
14
|
+
else
|
15
|
+
def __insert_and_return__(dataset, pkey, params)
|
16
|
+
id = dataset.insert(params)
|
17
|
+
dataset.where(pkey => id).first
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
if dataset.supports_returning?(:update)
|
22
|
+
def __update_and_return__(dataset, params)
|
23
|
+
dataset.returning.update(params).first
|
24
|
+
end
|
25
|
+
else
|
26
|
+
def __update_and_return__(dataset, params)
|
27
|
+
dataset.update(params)
|
28
|
+
dataset.first
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if dataset.respond_to?(:supports_insert_conflict?) && dataset.supports_insert_conflict?
|
33
|
+
def __insert_or_update_and_return__(dataset, pkey, unique_columns, params, conds = nil, exclude_on_update = nil)
|
34
|
+
to_update = params.keys - unique_columns
|
35
|
+
to_update -= exclude_on_update if exclude_on_update
|
36
|
+
|
37
|
+
dataset = dataset.insert_conflict(
|
38
|
+
target: unique_columns,
|
39
|
+
update: Hash[ to_update.map { |attribute| [attribute, Sequel[:excluded][attribute]] } ],
|
40
|
+
update_where: conds
|
41
|
+
)
|
42
|
+
|
43
|
+
__insert_and_return__(dataset, pkey, params)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
def __insert_or_update_and_return__(dataset, pkey, unique_columns, params, conds = nil, exclude_on_update = nil)
|
47
|
+
find_params, update_params = params.partition { |key, _| unique_columns.include?(key) }.map { |h| Hash[h] }
|
48
|
+
|
49
|
+
dataset_where = dataset.where(find_params)
|
50
|
+
record = if conds
|
51
|
+
dataset_where_conds = dataset_where.where(conds)
|
52
|
+
|
53
|
+
# this means that there's still a valid entry there, so return early
|
54
|
+
return if dataset_where.count != dataset_where_conds.count
|
55
|
+
|
56
|
+
dataset_where_conds.first
|
57
|
+
else
|
58
|
+
dataset_where.first
|
59
|
+
end
|
60
|
+
|
61
|
+
if record
|
62
|
+
update_params.reject! { |k, _v| exclude_on_update.include?(k) } if exclude_on_update
|
63
|
+
__update_and_return__(dataset_where, update_params)
|
64
|
+
else
|
65
|
+
__insert_and_return__(dataset, pkey, params)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
# rubocop:enable Naming/MethodName, Metrics/ParameterLists
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<form method="post" class="form-horizontal" role="form" id="authorize-form">
|
2
|
+
#{csrf_tag(rodauth.authorize_path) if respond_to?(:csrf_tag)}
|
3
|
+
<p class="lead">The application #{rodauth.oauth_application[rodauth.oauth_applications_name_column]} would like to access your data.</p>
|
4
|
+
|
5
|
+
<div class="form-group">
|
6
|
+
<h1 class="display-6">#{rodauth.scopes_label}</h1>
|
7
|
+
|
8
|
+
#{
|
9
|
+
rodauth.scopes.map do |scope|
|
10
|
+
<<-HTML
|
11
|
+
<div class="form-check">
|
12
|
+
<input id="#{scope}" class="form-check-input" type="checkbox" name="scope[]" value="#{scope}" #{"checked disabled" if scope == rodauth.oauth_application_default_scope}>
|
13
|
+
<label class="form-check-label" for="#{scope}">#{scope}</label>
|
14
|
+
</div>
|
15
|
+
HTML
|
16
|
+
end.join
|
17
|
+
}
|
18
|
+
|
19
|
+
<input type="hidden" name="client_id" value="#{rodauth.param("client_id")}"/>
|
20
|
+
|
21
|
+
#{"<input type=\"hidden\" name=\"access_type\" value=\"#{rodauth.param("access_type")}\"/>" if rodauth.param_or_nil("access_type")}
|
22
|
+
#{"<input type=\"hidden\" name=\"response_type\" value=\"#{rodauth.param("response_type")}\"/>" if rodauth.param_or_nil("response_type")}
|
23
|
+
#{"<input type=\"hidden\" name=\"response_mode\" value=\"#{rodauth.param("response_mode")}\"/>" if rodauth.param_or_nil("response_mode")}
|
24
|
+
#{"<input type=\"hidden\" name=\"state\" value=\"#{rodauth.param("state")}\"/>" if rodauth.param_or_nil("state")}
|
25
|
+
#{"<input type=\"hidden\" name=\"nonce\" value=\"#{rodauth.param("nonce")}\"/>" if rodauth.param_or_nil("nonce")}
|
26
|
+
#{"<input type=\"hidden\" name=\"redirect_uri\" value=\"#{rodauth.redirect_uri}\"/>" if rodauth.param_or_nil("redirect_uri")}
|
27
|
+
#{"<input type=\"hidden\" name=\"code_challenge\" value=\"#{rodauth.param("code_challenge")}\"/>" if rodauth.param_or_nil("code_challenge")}
|
28
|
+
#{"<input type=\"hidden\" name=\"code_challenge_method\" value=\"#{rodauth.param("code_challenge_method")}\"/>" if rodauth.param_or_nil("code_challenge_method")}
|
29
|
+
</div>
|
30
|
+
<p class="text-center">
|
31
|
+
<input type="submit" class="btn btn-outline-primary" value="#{h(rodauth.oauth_authorize_button)}"/>
|
32
|
+
<a href="#{rodauth.redirect_uri}?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request#{ "&state=#{rodauth.param("state")}" if rodauth.param_or_nil("state")}" class="btn btn-outline-danger">Cancel</a>
|
33
|
+
</p>
|
34
|
+
</form>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<form method="post" action="#{rodauth.oauth_applications_path}" class="rodauth" role="form" id="oauth-application-form">
|
2
|
+
#{rodauth.csrf_tag}
|
3
|
+
#{rodauth.render('name_field')}
|
4
|
+
#{rodauth.render('description_field')}
|
5
|
+
#{rodauth.render('homepage_url_field')}
|
6
|
+
#{rodauth.render('redirect_uri_field')}
|
7
|
+
#{rodauth.render('client_secret_field')}
|
8
|
+
#{rodauth.render('scope_field')}
|
9
|
+
#{rodauth.button(rodauth.oauth_application_button)}
|
10
|
+
</form>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<div id="oauth-application">
|
2
|
+
<dl>
|
3
|
+
#{
|
4
|
+
(rodauth.oauth_application_required_params + %w[client_id] - %w[client_secret]).map do |param|
|
5
|
+
"<dt class=\"#{param}\">#{rodauth.send(:"#{param}_label")}</dt>" +
|
6
|
+
"<dd class=\"#{param}\">#{@oauth_application[rodauth.send(:"oauth_applications_#{param}_column")]}</dd>"
|
7
|
+
end.join
|
8
|
+
}
|
9
|
+
</dl>
|
10
|
+
<a href="/#{"#{rodauth.oauth_applications_path}/#{@oauth_application[:id]}/#{rodauth.oauth_tokens_path}"}" class="btn btn-outline-secondary">Oauth Tokens</a>
|
11
|
+
</div>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div id="oauth-applications">
|
2
|
+
<a class="btn btn-outline-primary" href="/oauth-applications/new">Register new Oauth Application</a>
|
3
|
+
#{
|
4
|
+
if @oauth_applications.count.zero?
|
5
|
+
"<p>No oauth applications yet!</p>"
|
6
|
+
else
|
7
|
+
"<ul class=\"list-group\">" +
|
8
|
+
@oauth_applications.map do |application|
|
9
|
+
"<li class=\"list-group-item\"><a href=\"/oauth-applications/#{application[:id]}\">#{application[:name]}</a></li>"
|
10
|
+
end.join +
|
11
|
+
"</ul>"
|
12
|
+
end
|
13
|
+
}
|
14
|
+
</div>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<div id="oauth-tokens">
|
2
|
+
#{
|
3
|
+
if @oauth_tokens.count.zero?
|
4
|
+
"<p>No oauth tokens yet!</p>"
|
5
|
+
else
|
6
|
+
<<-HTML
|
7
|
+
<table class="table">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th scope="col">Token</th>
|
11
|
+
<th scope="col">Refresh Token</th>
|
12
|
+
<th scope="col">Expires in</th>
|
13
|
+
<th scope="col">Revoke</th>
|
14
|
+
<th scope="col"><span class="badge badge-pill badge-dark">#{@oauth_tokens.count}</span>
|
15
|
+
</tr>
|
16
|
+
</thead>
|
17
|
+
<tbody>
|
18
|
+
#{
|
19
|
+
@oauth_tokens.map do |oauth_token|
|
20
|
+
<<-HTML
|
21
|
+
<tr>
|
22
|
+
<td>#{oauth_token[rodauth.oauth_tokens_token_column]}</td>
|
23
|
+
<td>#{oauth_token[rodauth.oauth_tokens_refresh_token_column]}</td>
|
24
|
+
<td>#{rodauth.convert_timestamp(oauth_token[rodauth.oauth_tokens_expires_in_column])}</td>
|
25
|
+
<td>#{rodauth.convert_timestamp(oauth_token[rodauth.oauth_tokens_revoked_at_column])}</td>
|
26
|
+
<td>
|
27
|
+
#{
|
28
|
+
if !oauth_token[rodauth.oauth_tokens_revoked_at_param] && !oauth_token[rodauth.oauth_tokens_token_hash_column]
|
29
|
+
<<-HTML
|
30
|
+
<form method="post" action="#{rodauth.revoke_path}" class="form-horizontal" role="form" id="revoke-form">
|
31
|
+
#{csrf_tag(rodauth.oauth_revoke_path) if respond_to?(:csrf_tag)}
|
32
|
+
#{rodauth.input_field_string("token_type_hint", "revoke-token-type-hint", :value => "access_token", :type=>"hidden")}
|
33
|
+
#{rodauth.input_field_string("token", "revoke-token", :value => oauth_token[rodauth.oauth_tokens_token_column], :type=>"hidden")}
|
34
|
+
#{rodauth.button(rodauth.oauth_token_revoke_button)}
|
35
|
+
</form>
|
36
|
+
HTML
|
37
|
+
end
|
38
|
+
}
|
39
|
+
</td>
|
40
|
+
</tr>
|
41
|
+
HTML
|
42
|
+
end.join
|
43
|
+
}
|
44
|
+
</tbody>
|
45
|
+
</table>
|
46
|
+
HTML
|
47
|
+
end
|
48
|
+
}
|
49
|
+
</div>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<fieldset class="form-group">
|
2
|
+
#{
|
3
|
+
rodauth.oauth_application_scopes.map do |scope|
|
4
|
+
"<div class=\"form-check checkbox\">" +
|
5
|
+
"<input id=\"#{scope}\" type=\"checkbox\" name=\"#{rodauth.oauth_application_scopes_param}[]\" value=\"#{scope}\">" +
|
6
|
+
"<label for=\"#{scope}\">#{scope}</label>" +
|
7
|
+
"</div>"
|
8
|
+
end.join
|
9
|
+
}
|
10
|
+
</fieldset>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth-oauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Implementation of the OAuth 2.0 protocol on top of rodauth.
|
14
14
|
email:
|
@@ -32,17 +32,30 @@ files:
|
|
32
32
|
- lib/rodauth/features/oauth.rb
|
33
33
|
- lib/rodauth/features/oauth_http_mac.rb
|
34
34
|
- lib/rodauth/features/oauth_jwt.rb
|
35
|
+
- lib/rodauth/features/oauth_saml.rb
|
35
36
|
- lib/rodauth/features/oidc.rb
|
36
37
|
- lib/rodauth/oauth.rb
|
38
|
+
- lib/rodauth/oauth/database_extensions.rb
|
37
39
|
- lib/rodauth/oauth/railtie.rb
|
38
40
|
- lib/rodauth/oauth/ttl_store.rb
|
39
41
|
- lib/rodauth/oauth/version.rb
|
40
|
-
|
42
|
+
- templates/authorize.str
|
43
|
+
- templates/client_secret_field.str
|
44
|
+
- templates/description_field.str
|
45
|
+
- templates/homepage_url_field.str
|
46
|
+
- templates/name_field.str
|
47
|
+
- templates/new_oauth_application.str
|
48
|
+
- templates/oauth_application.str
|
49
|
+
- templates/oauth_applications.str
|
50
|
+
- templates/oauth_tokens.str
|
51
|
+
- templates/redirect_uri_field.str
|
52
|
+
- templates/scope_field.str
|
53
|
+
homepage: https://gitlab.com/honeyryderchuck/rodauth-oauth
|
41
54
|
licenses: []
|
42
55
|
metadata:
|
43
|
-
homepage_uri: https://gitlab.com/honeyryderchuck/
|
44
|
-
source_code_uri: https://gitlab.com/honeyryderchuck/
|
45
|
-
changelog_uri: https://gitlab.com/honeyryderchuck/
|
56
|
+
homepage_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth
|
57
|
+
source_code_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth
|
58
|
+
changelog_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth/-/blob/master/CHANGELOG.md
|
46
59
|
post_install_message:
|
47
60
|
rdoc_options: []
|
48
61
|
require_paths:
|
@@ -58,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
71
|
- !ruby/object:Gem::Version
|
59
72
|
version: '0'
|
60
73
|
requirements: []
|
61
|
-
rubygems_version: 3.1.
|
74
|
+
rubygems_version: 3.1.4
|
62
75
|
signing_key:
|
63
76
|
specification_version: 4
|
64
77
|
summary: Implementation of the OAuth 2.0 protocol on top of rodauth.
|