rodauth-oauth 1.6.7 → 1.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47de1ced2a621692058d69609ccb69999440ac8ca3de7f7a43f8522a81b93a20
4
- data.tar.gz: 4822470b6f682648a772b8d7244000a68557875ee12ebd2126033f58128d9241
3
+ metadata.gz: 86f6ed47ccab8da1af7b8be2bd1929e24c12f1fd6fa959a5edfdee273bd0b70d
4
+ data.tar.gz: 10e0c26c907bfb5027ce2f77d67f4a85135cae1bf487a33c0847914084423896
5
5
  SHA512:
6
- metadata.gz: 29604d9791ebdab3ea7a85a8ad05cc1ff32aaf8b73aad85b367be9cdd2ab5f199540d25b179147ef5346da7d709fcbf470aac05db6b903d80c483ce47214d399
7
- data.tar.gz: 7d853b0d1a139fe2d10ec2d865493c8bdf9db313df79e4778e44943900f5634eabb03ac851a65f4f0bc31708014b037116ac46bf150b9fed8bee93fab5f9909c
6
+ metadata.gz: 8564ff9e316d23f319b3f26746175971c0ac5d027f50ceade63728aaddd5013edf8b36ab9547be421525e15856234a69505c69c0cfa8176f24a770e7817b9a2e
7
+ data.tar.gz: d1e4d2f419de9dda4eafb7d91d320e3cbc80eae5ab511ad45ab5f52c4ec38f7b0c8c18b8154fd743f53b87028d77f789278530235ab336d0ee638a6b3f80f73f
data/README.md CHANGED
@@ -55,6 +55,7 @@ This gem implements the following RFCs and features of OAuth:
55
55
  * `oauth_dynamic_client_registration` - [Dynamic Client Registration Protocol](https://datatracker.ietf.org/doc/html/rfc7591) and [Dynamic Client Registration Management](https://www.rfc-editor.org/rfc/rfc7592);
56
56
  * OAuth application and token management dashboards;
57
57
  * The recommendations for [Native Apps](https://www.rfc-editor.org/rfc/rfc8252);
58
+ * `oauth_client_id_metadata_document` - [Client ID Metadata Document](https://datatracker.ietf.org/doc/draft-ietf-oauth-client-id-metadata-document/);
58
59
 
59
60
  It also implements several components of [OpenID Connect](https://openid.net/connect/) on top of the OAuth features it provides, including:
60
61
 
@@ -0,0 +1,9 @@
1
+ # 1.7.0
2
+
3
+ ## Features
4
+
5
+ ### Client ID Metadata Document Support
6
+
7
+ `rodauth-oauth` supports the Client ID Metadata Document Standard (also known as CIMD), via the `oauth_client_id_metadata_document` feature. In a nutshell, this provides a way by which a Client Application can identify itself to the authorization server, without prior dynamic client registration or other existing registration.
8
+
9
+ More info about the feature [in the docs](https://gitlab.com/os85/rodauth-oauth/-/wikis/Client-ID-Metadata-Document).
@@ -9,7 +9,8 @@ class CreateRodauthOauth < ActiveRecord::Migration<%= migration_version %>
9
9
  t.string :redirect_uri, null: false
10
10
  t.string :client_id, null: false, index: { unique: true }
11
11
  # change `:null` contraints to false if you want to support confidential clients only, and
12
- # no scheme relying on JWT private keys advertised by the JWKs uri.
12
+ # no scheme relying on JWT private keys advertised by the JWKs uri; keep this as true if
13
+ # supporting public clients or CIMD.
13
14
  t.string :client_secret, null: true, index: { unique: true }
14
15
  t.string :registration_access_token, null: true
15
16
  t.string :scopes, null: false
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rodauth/oauth"
4
+
5
+ module Rodauth
6
+ Feature.define(:oauth_client_id_metadata_document, :OauthClientIdMetadataDocument) do
7
+ depends :oauth_authorize_base
8
+
9
+ DOT_SEGMENTS = %w[. ..].freeze
10
+
11
+ FORBIDDEN_TOKEN_AUTH_METHODS = %w[client_secret_post client_secret_basic client_secret_jwt].freeze
12
+
13
+ def oauth_application
14
+ super || begin
15
+ client_id = param_or_nil("client_id")
16
+
17
+ return unless client_id && valid_cimd_url?(client_id)
18
+
19
+ return if @client_id_lookup
20
+
21
+ @client_id_lookup = true
22
+
23
+ client_metadata = http_request_with_cache(client_id)
24
+
25
+ # 4.1 The client metadata document MUST contain a client_id property whose value MUST match the URL of the document
26
+ redirect_response_error("invalid_request") unless client_metadata[:client_id] == client_id
27
+
28
+ validate_client_metadata_document(client_metadata)
29
+
30
+ @client_id_lookup = false
31
+
32
+ # rewrite metadata params into column names
33
+ create_params = Hash[
34
+ client_metadata.map do |k, v|
35
+ k = case k
36
+ when :redirect_uris
37
+ v = v.join(" ")
38
+ :redirect_uri
39
+ when :client_uri
40
+ :homepage_url
41
+ when :grant_types, :response_types, :contacts
42
+ v = v.join(" ")
43
+ k
44
+ when :client_name
45
+ :name
46
+ when :scope
47
+ :scopes
48
+ else
49
+ k
50
+ end
51
+ [send(:"oauth_applications_#{k}_column"), v]
52
+ end
53
+ ]
54
+
55
+ applications_ds = db[oauth_applications_table]
56
+ application_columns = applications_ds.columns
57
+
58
+ create_params.delete_if { |k, _| !application_columns.include?(k) }
59
+ @oauth_application = __insert_or_do_nothing_and_return__(
60
+ applications_ds,
61
+ oauth_applications_id_column,
62
+ [oauth_applications_client_id_column],
63
+ create_params
64
+ )
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def valid_cimd_url?(client_id)
71
+ return false unless URI::DEFAULT_PARSER.make_regexp("https").match?(client_id)
72
+
73
+ uri = URI(client_id)
74
+ # Client identifier URLs MUST have an "https" scheme,
75
+ return false unless uri.scheme == "https"
76
+
77
+ path = uri.path
78
+ # MUST contain a path component
79
+ return false if path.empty? ||
80
+ # MUST NOT contain single-dot or double-dot path segments
81
+ path.split("/").any? { |seg| DOT_SEGMENTS.include?(seg) }
82
+
83
+ return false unless
84
+ # MUST NOT contain a fragment component
85
+ (uri.fragment.nil? || uri.fragment.empty?) &&
86
+ # MUST NOT contain a username or password Client identifier URLs
87
+ (uri.userinfo.nil? || uri.userinfo.empty?) &&
88
+ # SHOULD NOT include a query string component, and MAY contain a port.
89
+ (uri.query.nil? || uri.query.empty?)
90
+
91
+ true
92
+ end
93
+
94
+ def validate_client_metadata_document(metadata)
95
+ if (token_endpoint_auth_method = metadata[:token_endpoint_auth_method]) &&
96
+ FORBIDDEN_TOKEN_AUTH_METHODS.include?(token_endpoint_auth_method)
97
+ # the token_endpoint_auth_method property MUST NOT include client_secret_post, client_secret_basic, client_secret_jwt,
98
+ # or any other method based around a shared symmetric secret
99
+ redirect_response_error("invalid_request")
100
+ end
101
+
102
+ # the client_secret and client_secret_expires_at properties MUST NOT be used
103
+ redirect_response_error("invalid_request") if metadata.key?(:client_secret) || metadata.key?(:client_secret_expires_at)
104
+ end
105
+
106
+ def oauth_server_metadata_body(*)
107
+ super.tap do |data|
108
+ data[:client_id_metadata_document_supported] = true
109
+ end
110
+ end
111
+ end
112
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rodauth
4
4
  module OAuth
5
- VERSION = "1.6.7"
5
+ VERSION = "1.7.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth-oauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.7
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
@@ -95,6 +95,7 @@ extra_rdoc_files:
95
95
  - doc/release_notes/1_6_5.md
96
96
  - doc/release_notes/1_6_6.md
97
97
  - doc/release_notes/1_6_7.md
98
+ - doc/release_notes/1_7_0.md
98
99
  files:
99
100
  - CHANGELOG.md
100
101
  - LICENSE.txt
@@ -148,6 +149,7 @@ files:
148
149
  - doc/release_notes/1_6_5.md
149
150
  - doc/release_notes/1_6_6.md
150
151
  - doc/release_notes/1_6_7.md
152
+ - doc/release_notes/1_7_0.md
151
153
  - lib/generators/rodauth/oauth/install_generator.rb
152
154
  - lib/generators/rodauth/oauth/templates/app/models/oauth_application.rb
153
155
  - lib/generators/rodauth/oauth/templates/app/models/oauth_grant.rb
@@ -169,6 +171,7 @@ files:
169
171
  - lib/rodauth/features/oauth_authorize_base.rb
170
172
  - lib/rodauth/features/oauth_base.rb
171
173
  - lib/rodauth/features/oauth_client_credentials_grant.rb
174
+ - lib/rodauth/features/oauth_client_id_metadata_document.rb
172
175
  - lib/rodauth/features/oauth_device_code_grant.rb
173
176
  - lib/rodauth/features/oauth_dpop.rb
174
177
  - lib/rodauth/features/oauth_dynamic_client_registration.rb