rodauth-oauth 1.0.0.pre.beta1 → 1.0.0.pre.beta2

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.
@@ -6,6 +6,8 @@ module Rodauth
6
6
  Feature.define(:oauth_jwt_bearer_grant, :OauthJwtBearerGrant) do
7
7
  depends :oauth_assertion_base, :oauth_jwt
8
8
 
9
+ auth_value_method :max_param_bytesize, nil if Rodauth::VERSION >= "2.26.0"
10
+
9
11
  auth_value_methods(
10
12
  :require_oauth_application_from_jwt_bearer_assertion_issuer,
11
13
  :require_oauth_application_from_jwt_bearer_assertion_subject,
@@ -54,7 +56,7 @@ module Rodauth
54
56
 
55
57
  def require_oauth_application_from_client_secret_jwt(client_id, assertion, alg)
56
58
  oauth_application = db[oauth_applications_table].where(oauth_applications_client_id_column => client_id).first
57
- authorization_required unless supports_auth_method?(oauth_application, "client_secret_jwt")
59
+ authorization_required unless oauth_application && supports_auth_method?(oauth_application, "client_secret_jwt")
58
60
  client_secret = oauth_application[oauth_applications_client_secret_column]
59
61
  claims = jwt_assertion(assertion, jws_key: client_secret, jws_algorithm: alg)
60
62
  authorization_required unless claims && claims["iss"] == client_id
@@ -63,7 +65,7 @@ module Rodauth
63
65
 
64
66
  def require_oauth_application_from_private_key_jwt(client_id, assertion)
65
67
  oauth_application = db[oauth_applications_table].where(oauth_applications_client_id_column => client_id).first
66
- authorization_required unless supports_auth_method?(oauth_application, "private_key_jwt")
68
+ authorization_required unless oauth_application && supports_auth_method?(oauth_application, "private_key_jwt")
67
69
  jwks = oauth_application_jwks(oauth_application)
68
70
  claims = jwt_assertion(assertion, jwks: jwks)
69
71
  authorization_required unless claims
@@ -79,8 +81,9 @@ module Rodauth
79
81
  end
80
82
 
81
83
  def jwt_assertion(assertion, **kwargs)
82
- claims = jwt_decode(assertion, verify_iss: false, verify_aud: false, **kwargs)
83
- return unless verify_aud(request.url, claims["aud"])
84
+ claims = jwt_decode(assertion, verify_iss: false, verify_aud: false, verify_jti: false, **kwargs)
85
+
86
+ return unless claims && verify_aud(request.url, claims["aud"])
84
87
 
85
88
  claims
86
89
  end
@@ -4,31 +4,46 @@ require "rodauth/oauth"
4
4
 
5
5
  module Rodauth
6
6
  Feature.define(:oauth_jwt_secured_authorization_request, :OauthJwtSecuredAuthorizationRequest) do
7
+ ALLOWED_REQUEST_URI_CONTENT_TYPES = %w[application/jose application/oauth-authz-req+jwt].freeze
8
+
7
9
  depends :oauth_authorize_base, :oauth_jwt_base
8
10
 
11
+ auth_value_method :oauth_require_request_uri_registration, false
12
+ auth_value_method :oauth_request_object_signing_alg_allow_none, false
13
+
14
+ auth_value_method :oauth_applications_request_uris_column, :request_uris
15
+
9
16
  auth_value_method :oauth_applications_request_object_signing_alg_column, :request_object_signing_alg
10
17
  auth_value_method :oauth_applications_request_object_encryption_alg_column, :request_object_encryption_alg
11
18
  auth_value_method :oauth_applications_request_object_encryption_enc_column, :request_object_encryption_enc
12
19
 
13
- translatable_method :oauth_request_uri_not_supported_message, "request uri is unsupported"
14
20
  translatable_method :oauth_invalid_request_object_message, "request object is invalid"
15
21
 
22
+ auth_value_method :max_param_bytesize, nil if Rodauth::VERSION >= "2.26.0"
23
+
16
24
  private
17
25
 
18
26
  # /authorize
19
27
 
20
28
  def validate_authorize_params
21
- # TODO: add support for requst_uri
22
- redirect_response_error("request_uri_not_supported") if param_or_nil("request_uri")
23
-
24
29
  request_object = param_or_nil("request")
25
30
 
26
- return super unless request_object && oauth_application
31
+ request_uri = param_or_nil("request_uri")
27
32
 
28
- if (jwks = oauth_application_jwks(oauth_application))
29
- jwks = JSON.parse(jwks, symbolize_names: true) if jwks.is_a?(String)
30
- else
31
- redirect_response_error("invalid_request_object")
33
+ return super unless (request_object || request_uri) && oauth_application
34
+
35
+ if request_uri
36
+ request_uri = CGI.unescape(request_uri)
37
+
38
+ redirect_response_error("invalid_request_uri") unless supported_request_uri?(request_uri, oauth_application)
39
+
40
+ response = http_request(request_uri)
41
+
42
+ unless response.code.to_i == 200 && ALLOWED_REQUEST_URI_CONTENT_TYPES.include?(response["content-type"])
43
+ redirect_response_error("invalid_request_uri")
44
+ end
45
+
46
+ request_object = response.body
32
47
  end
33
48
 
34
49
  request_sig_enc_opts = {
@@ -37,10 +52,33 @@ module Rodauth
37
52
  jws_encryption_method: oauth_application[oauth_applications_request_object_encryption_enc_column]
38
53
  }.compact
39
54
 
40
- claims = jwt_decode(request_object, jwks: jwks, verify_jti: false, verify_aud: false, **request_sig_enc_opts)
55
+ request_sig_enc_opts[:jws_algorithm] ||= "none" if oauth_request_object_signing_alg_allow_none
56
+
57
+ if request_sig_enc_opts[:jws_algorithm] == "none"
58
+ jwks = nil
59
+ elsif (jwks = oauth_application_jwks(oauth_application))
60
+ jwks = JSON.parse(jwks, symbolize_names: true) if jwks.is_a?(String)
61
+ else
62
+ redirect_response_error("invalid_request_object")
63
+ end
64
+
65
+ claims = jwt_decode(request_object,
66
+ jwks: jwks,
67
+ verify_jti: false,
68
+ verify_iss: false,
69
+ verify_aud: false,
70
+ **request_sig_enc_opts)
41
71
 
42
72
  redirect_response_error("invalid_request_object") unless claims
43
73
 
74
+ if (iss = claims["iss"]) && (iss != oauth_application[oauth_applications_client_id_column])
75
+ redirect_response_error("invalid_request_object")
76
+ end
77
+
78
+ if (aud = claims["aud"]) && !verify_aud(aud, oauth_jwt_issuer)
79
+ redirect_response_error("invalid_request_object")
80
+ end
81
+
44
82
  # If signed, the Authorization Request
45
83
  # Object SHOULD contain the Claims "iss" (issuer) and "aud" (audience)
46
84
  # as members, with their semantics being the same as defined in the JWT
@@ -58,5 +96,21 @@ module Rodauth
58
96
 
59
97
  super
60
98
  end
99
+
100
+ def supported_request_uri?(request_uri, oauth_application)
101
+ return false unless check_valid_uri?(request_uri)
102
+
103
+ request_uris = oauth_application[oauth_applications_request_uris_column]
104
+
105
+ request_uris.nil? || request_uris.split(oauth_scope_separator).one? { |uri| request_uri.start_with?(uri) }
106
+ end
107
+
108
+ def oauth_server_metadata_body(*)
109
+ super.tap do |data|
110
+ data[:request_parameter_supported] = true
111
+ data[:request_uri_parameter_supported] = true
112
+ data[:require_request_uri_registration] = oauth_require_request_uri_registration
113
+ end
114
+ end
61
115
  end
62
116
  end
@@ -70,10 +70,6 @@ module Rodauth
70
70
  super(oauth_grant, update_params.merge(oauth_grants_resource_column => resource_indicators))
71
71
  end
72
72
 
73
- def check_valid_no_fragment_uri?(uri)
74
- check_valid_uri?(uri) && URI.parse(uri).fragment.nil?
75
- end
76
-
77
73
  module IndicatorAuthorizationCodeGrant
78
74
  private
79
75
 
@@ -16,12 +16,12 @@ module Rodauth
16
16
  return @authorization_token if defined?(@authorization_token)
17
17
 
18
18
  # check if there is a token
19
- bearer_token = fetch_access_token
19
+ access_token = fetch_access_token
20
20
 
21
- return unless bearer_token
21
+ return unless access_token
22
22
 
23
23
  # where in resource server, NOT the authorization server.
24
- payload = introspection_request("access_token", bearer_token)
24
+ payload = introspection_request("access_token", access_token)
25
25
 
26
26
  return unless payload["active"]
27
27
 
@@ -17,6 +17,8 @@ module Rodauth
17
17
  auth_value_method :oauth_saml_security_digest_method, XMLSecurity::Document::SHA1
18
18
  auth_value_method :oauth_saml_security_signature_method, XMLSecurity::Document::RSA_SHA1
19
19
 
20
+ auth_value_method :max_param_bytesize, nil if Rodauth::VERSION >= "2.26.0"
21
+
20
22
  auth_value_methods(
21
23
  :require_oauth_application_from_saml2_bearer_assertion_issuer,
22
24
  :require_oauth_application_from_saml2_bearer_assertion_subject,