From 9229ebcdad75e091c84e9d35a11ec0d956617978 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 16 Jun 2025 14:12:16 -0700 Subject: [PATCH 01/19] Use context in sign --- .../lib/smithy-client/plugins/sign_requests.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb b/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb index 06a410390..acd4760a0 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb @@ -8,11 +8,7 @@ class SignRequests < Plugin # @api private class Handler < Client::Handler def call(context) - context[:auth].signer.sign( - request: context.request, - identity: context[:auth].identity, - properties: context[:auth].signer_properties - ) + context[:auth].signer.sign(context) @handler.call(context) end end From 8a9df8201235c1ed21489d10c46b6f9780077f75 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 17 Jun 2025 10:07:43 -0700 Subject: [PATCH 02/19] Test basic approach --- .../smithy/templates/client/auth_plugin.erb | 29 +++++++++---------- .../smithy/templates/client/auth_resolver.erb | 4 +++ .../lib/smithy/views/client/auth_resolver.rb | 6 ++-- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb index b8ef3b1f2..9b568b308 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb @@ -36,13 +36,14 @@ module <%= module_name %> # TODO: apply endpoint auth properties if present auth_params = AuthParameters.create(context) auth_options = context.config.auth_resolver.resolve(auth_params) - context[:auth] = resolve_auth(context, auth_options) + signing_name = context.config.auth_resolver.signing_name + context[:auth] = resolve_auth(context, auth_options, signing_name) @handler.call(context) end private - def resolve_auth(context, auth_options) + def resolve_auth(context, auth_options, signing_name) failures = [] raise 'No auth options were resolved' if auth_options.empty? @@ -54,12 +55,13 @@ module <%= module_name %> } auth_options.each do |auth_option| - auth_scheme = context.config.auth_schemes[auth_option.scheme_id] + auth_scheme = context.config.auth_schemes[auth_option] resolved_auth = try_load_auth_scheme( auth_option, auth_scheme, identity_providers, - failures + failures, + signing_name ) return resolved_auth if resolved_auth @@ -68,8 +70,8 @@ module <%= module_name %> raise failures.join("\n") end - def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) - scheme_id = auth_option.scheme_id + def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures, signing_name) + scheme_id = auth_option unless auth_scheme failures << "Auth scheme #{scheme_id} was not enabled " \ 'for this request' @@ -83,29 +85,24 @@ module <%= module_name %> return end - identity_properties = auth_option.identity_properties - identity = identity_provider.identity(identity_properties) + identity = identity_provider.identity({}) ResolvedAuth.new( - scheme_id: scheme_id, identity: identity, - identity_properties: auth_option.identity_properties, signer: auth_scheme.signer, - signer_properties: auth_option.signer_properties + signing_name: signing_name ) end # @api private class ResolvedAuth def initialize(options = {}) - @scheme_id = options[:scheme_id] - @signer = options[:signer] - @signer_properties = options[:signer_properties] @identity = options[:identity] - @identity_properties = options[:identity_properties] + @signer = options[:signer] + @signing_name = options[:signing_name] end - attr_accessor :scheme_id, :signer, :signer_properties, :identity, :identity_properties + attr_accessor :identity, :signer, :signing_name end end diff --git a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb index 2288eabe1..82eccb65e 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb @@ -12,5 +12,9 @@ module <%= module_name %> <%= line %> <% end -%> end + + def signing_name + '<%= signing_name %>' + end end end diff --git a/gems/smithy/lib/smithy/views/client/auth_resolver.rb b/gems/smithy/lib/smithy/views/client/auth_resolver.rb index 77d036cb7..dbf6e3318 100644 --- a/gems/smithy/lib/smithy/views/client/auth_resolver.rb +++ b/gems/smithy/lib/smithy/views/client/auth_resolver.rb @@ -116,9 +116,11 @@ def add_registered_auth_schemes(auth_schemes, traits) end def render_auth_option(auth_scheme) - properties = @service_traits.fetch(auth_scheme, {}) - "Smithy::Client::AuthOption.new(scheme_id: '#{auth_scheme}', signer_properties: #{properties})" + @signing_name = @service_traits.fetch(auth_scheme, {}).fetch('name', '') + "'#{auth_scheme}'" end + + attr_reader :signing_name end end end From d1317cc38e62c95523496b55e0e84c3b275e9d08 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 17 Jun 2025 11:10:14 -0700 Subject: [PATCH 03/19] Service shape approach --- .../lib/smithy/templates/client/auth_plugin.erb | 16 ++++++---------- .../smithy/templates/client/auth_resolver.erb | 4 ---- .../lib/smithy/views/client/auth_resolver.rb | 3 --- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb index 9b568b308..a58e0aee2 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb @@ -36,14 +36,13 @@ module <%= module_name %> # TODO: apply endpoint auth properties if present auth_params = AuthParameters.create(context) auth_options = context.config.auth_resolver.resolve(auth_params) - signing_name = context.config.auth_resolver.signing_name - context[:auth] = resolve_auth(context, auth_options, signing_name) + context[:auth] = resolve_auth(context, auth_options) @handler.call(context) end private - def resolve_auth(context, auth_options, signing_name) + def resolve_auth(context, auth_options) failures = [] raise 'No auth options were resolved' if auth_options.empty? @@ -60,8 +59,7 @@ module <%= module_name %> auth_option, auth_scheme, identity_providers, - failures, - signing_name + failures ) return resolved_auth if resolved_auth @@ -70,7 +68,7 @@ module <%= module_name %> raise failures.join("\n") end - def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures, signing_name) + def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) scheme_id = auth_option unless auth_scheme failures << "Auth scheme #{scheme_id} was not enabled " \ @@ -89,8 +87,7 @@ module <%= module_name %> ResolvedAuth.new( identity: identity, - signer: auth_scheme.signer, - signing_name: signing_name + signer: auth_scheme.signer ) end @@ -99,10 +96,9 @@ module <%= module_name %> def initialize(options = {}) @identity = options[:identity] @signer = options[:signer] - @signing_name = options[:signing_name] end - attr_accessor :identity, :signer, :signing_name + attr_accessor :identity, :signer end end diff --git a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb index 82eccb65e..2288eabe1 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb @@ -12,9 +12,5 @@ module <%= module_name %> <%= line %> <% end -%> end - - def signing_name - '<%= signing_name %>' - end end end diff --git a/gems/smithy/lib/smithy/views/client/auth_resolver.rb b/gems/smithy/lib/smithy/views/client/auth_resolver.rb index dbf6e3318..1a382f29f 100644 --- a/gems/smithy/lib/smithy/views/client/auth_resolver.rb +++ b/gems/smithy/lib/smithy/views/client/auth_resolver.rb @@ -116,11 +116,8 @@ def add_registered_auth_schemes(auth_schemes, traits) end def render_auth_option(auth_scheme) - @signing_name = @service_traits.fetch(auth_scheme, {}).fetch('name', '') "'#{auth_scheme}'" end - - attr_reader :signing_name end end end From ebcadee0d55860781063f09f0f8dc621832a2677 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 19 Jun 2025 12:02:14 -0700 Subject: [PATCH 04/19] Refactor sign --- gems/smithy-client/lib/smithy-client.rb | 1 - .../lib/smithy-client/auth_option.rb | 23 ----------- .../lib/smithy-client/signers/anonymous.rb | 2 +- .../lib/smithy-client/signers/http_api_key.rb | 7 +++- .../lib/smithy-client/signers/http_basic.rb | 6 +-- .../lib/smithy-client/signers/http_bearer.rb | 4 +- .../lib/smithy-client/signers/http_digest.rb | 2 +- .../sig/smithy-client/auth_option.rbs | 10 ----- .../spec/smithy-client/auth_option_spec.rb | 39 ------------------- .../smithy/templates/client/auth_resolver.erb | 2 +- .../templates/client/auth_resolver_rbs.erb | 2 +- .../interfaces/client/auth_resolver_spec.rb | 10 ++--- .../shapes/lib/shapes/auth_resolver.rb | 4 +- projections/shapes/lib/shapes/plugins/auth.rb | 19 +++------ .../shapes/sig/shapes/auth_resolver.rbs | 2 +- .../weather/lib/weather/auth_resolver.rb | 4 +- .../weather/lib/weather/plugins/auth.rb | 19 +++------ .../weather/sig/weather/auth_resolver.rbs | 2 +- 18 files changed, 37 insertions(+), 121 deletions(-) delete mode 100644 gems/smithy-client/lib/smithy-client/auth_option.rb delete mode 100644 gems/smithy-client/sig/smithy-client/auth_option.rbs delete mode 100644 gems/smithy-client/spec/smithy-client/auth_option_spec.rb diff --git a/gems/smithy-client/lib/smithy-client.rb b/gems/smithy-client/lib/smithy-client.rb index 6c9f621e4..0844a5fc5 100644 --- a/gems/smithy-client/lib/smithy-client.rb +++ b/gems/smithy-client/lib/smithy-client.rb @@ -45,7 +45,6 @@ # identity and auth -require_relative 'smithy-client/auth_option' require_relative 'smithy-client/auth_scheme' require_relative 'smithy-client/identity' require_relative 'smithy-client/refreshing_identity_provider' diff --git a/gems/smithy-client/lib/smithy-client/auth_option.rb b/gems/smithy-client/lib/smithy-client/auth_option.rb deleted file mode 100644 index d60ca9d97..000000000 --- a/gems/smithy-client/lib/smithy-client/auth_option.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Smithy - module Client - # Object that represents an auth option, returned by Auth Resolvers. - class AuthOption - def initialize(scheme_id:, identity_properties: {}, signer_properties: {}) - @scheme_id = scheme_id - @identity_properties = identity_properties - @signer_properties = signer_properties - end - - # @return [String] - attr_reader :scheme_id - - # @return [Hash] - attr_reader :identity_properties - - # @return [Hash] - attr_reader :signer_properties - end - end -end diff --git a/gems/smithy-client/lib/smithy-client/signers/anonymous.rb b/gems/smithy-client/lib/smithy-client/signers/anonymous.rb index 63c256186..a29c756cf 100644 --- a/gems/smithy-client/lib/smithy-client/signers/anonymous.rb +++ b/gems/smithy-client/lib/smithy-client/signers/anonymous.rb @@ -5,7 +5,7 @@ module Client module Signers # A signer that does not sign requests. class Anonymous < Signer - def sign(**); end + def sign(context); end def reset(**); end end end diff --git a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb index b1c21e9f6..de3adec8a 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb @@ -5,8 +5,11 @@ module Client module Signers # A signer that signs requests using the HTTP API Key Auth scheme. class HttpApiKey < Signer - def sign(request:, identity:, properties:) - case properties['in'] + def sign(context) + request = context.request + identity = context[:auth].identity + location = context.config.service.traits['smithy.api#httpApiKeyAuth']['in'] + case location when 'header' value = "#{properties['scheme']} #{identity.key}".strip request.headers[properties['name']] = value diff --git a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb index 475e76b29..dbb64bed5 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb @@ -7,11 +7,11 @@ module Client module Signers # A signer that signs requests using the HTTP Basic Auth scheme. class HttpBasic < Signer - def sign(request:, identity:, **_options) + def sign(context) # TODO: does not handle realm or other properties - identity_string = "#{identity.username}:#{identity.password}" + identity_string = "#{context[:auth].identity.username}:#{context[:auth].identity.password}" encoded = Base64.strict_encode64(identity_string) - request.headers['Authorization'] = "Basic #{encoded}" + context.request.headers['Authorization'] = "Basic #{encoded}" end def reset(request:, **_options) diff --git a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb index a9239d158..d102c1994 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb @@ -5,9 +5,9 @@ module Client module Signers # A signer that signs requests using the HTTP Bearer Auth scheme. class HttpBearer < Signer - def sign(request:, identity:, **_options) + def sign(context) # TODO: does not handle realm or other properties - request.headers['Authorization'] = "Bearer #{identity.token}" + context.request.headers['Authorization'] = "Bearer #{context[:auth].identity.token}" end def reset(request:, **_options) diff --git a/gems/smithy-client/lib/smithy-client/signers/http_digest.rb b/gems/smithy-client/lib/smithy-client/signers/http_digest.rb index 64fb145e4..08852b5ee 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_digest.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_digest.rb @@ -5,7 +5,7 @@ module Client module Signers # A signer that signs requests using the HTTP Digest Auth scheme. class HttpDigest < Signer - def sign(request:, identity:, **_options) + def sign(context) # TODO: requires a nonce from the server - this cannot # be implemented unless we rescue from a 401 and retry # with the nonce diff --git a/gems/smithy-client/sig/smithy-client/auth_option.rbs b/gems/smithy-client/sig/smithy-client/auth_option.rbs deleted file mode 100644 index 256b58d54..000000000 --- a/gems/smithy-client/sig/smithy-client/auth_option.rbs +++ /dev/null @@ -1,10 +0,0 @@ -module Smithy - module Client - class AuthOption - def initialize: (scheme_id: String, ?identity_properties: Hash[String, untyped], ?signer_properties: Hash[String, untyped]) -> void - attr_reader scheme_id: String - attr_reader identity_properties: Hash[String, untyped] - attr_reader signer_properties: Hash[String, untyped] - end - end -end diff --git a/gems/smithy-client/spec/smithy-client/auth_option_spec.rb b/gems/smithy-client/spec/smithy-client/auth_option_spec.rb deleted file mode 100644 index 3975a6e7e..000000000 --- a/gems/smithy-client/spec/smithy-client/auth_option_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -require_relative '../spec_helper' - -module Smithy - module Client - describe AuthOption do - let(:scheme_id) { 'scheme_id' } - let(:identity_properties) { { 'identity' => 'property' } } - let(:signer_properties) { { 'signer' => 'property' } } - - subject do - AuthOption.new( - scheme_id: scheme_id, - identity_properties: identity_properties, - signer_properties: signer_properties - ) - end - - describe '#scheme_id' do - it 'returns the scheme_id' do - expect(subject.scheme_id).to eq(scheme_id) - end - end - - describe '#identity_properties' do - it 'returns the identity_properties' do - expect(subject.identity_properties).to eq(identity_properties) - end - end - - describe '#signer_properties' do - it 'returns the signer_properties' do - expect(subject.signer_properties).to eq(signer_properties) - end - end - end - end -end diff --git a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb index 2288eabe1..4d1545d85 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb @@ -6,7 +6,7 @@ module <%= module_name %> # Resolves the auth scheme from {AuthParameters}. class AuthResolver # @param [AuthParameters] parameters - # @return [Smithy::Client::AuthOption] + # @return [String] def resolve(parameters) <% auth_rules_code.each do |line| -%> <%= line %> diff --git a/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb b/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb index b615ea66f..317925dd6 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb @@ -1,5 +1,5 @@ module <%= module_name %> class AuthResolver - def resolve: (AuthParameters) -> Array[Smithy::Client::AuthOption] + def resolve: (AuthParameters) -> Array[String] end end diff --git a/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb b/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb index a89608e8f..2ca811ab5 100644 --- a/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb +++ b/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb @@ -16,13 +16,13 @@ params = NoAuthTrait::AuthParameters.new(operation_name: :operation_a) auth_options = subject.resolve(params) expected = %w[smithy.api#httpBasicAuth smithy.api#httpBearerAuth smithy.api#httpDigestAuth] - expect(auth_options.map(&:scheme_id)).to eq(expected) + expect(auth_options).to eq(expected) end it 'returns the auth options for the operation with the auth trait' do params = NoAuthTrait::AuthParameters.new(operation_name: :operation_b) auth_options = subject.resolve(params) - expect(auth_options.map(&:scheme_id)).to eq(['smithy.api#httpDigestAuth']) + expect(auth_options).to eq(['smithy.api#httpDigestAuth']) end end end @@ -37,19 +37,19 @@ params = AuthTrait::AuthParameters.new(operation_name: :operation_c) auth_options = subject.resolve(params) expected = %w[smithy.api#httpBasicAuth smithy.api#httpDigestAuth] - expect(auth_options.map(&:scheme_id)).to eq(expected) + expect(auth_options).to eq(expected) end it 'returns the auth options for the operation overriding the service auth trait' do params = AuthTrait::AuthParameters.new(operation_name: :operation_d) auth_options = subject.resolve(params) - expect(auth_options.map(&:scheme_id)).to eq(['smithy.api#httpBearerAuth']) + expect(auth_options).to eq(['smithy.api#httpBearerAuth']) end it 'returns a noAuth option when the auth trait is empty' do params = AuthTrait::AuthParameters.new(operation_name: :operation_e) auth_options = subject.resolve(params) - expect(auth_options.map(&:scheme_id)).to eq(['smithy.api#noAuth']) + expect(auth_options).to eq(['smithy.api#noAuth']) end end end diff --git a/projections/shapes/lib/shapes/auth_resolver.rb b/projections/shapes/lib/shapes/auth_resolver.rb index 073fd3a86..bad636518 100644 --- a/projections/shapes/lib/shapes/auth_resolver.rb +++ b/projections/shapes/lib/shapes/auth_resolver.rb @@ -6,10 +6,10 @@ module ShapeService # Resolves the auth scheme from {AuthParameters}. class AuthResolver # @param [AuthParameters] parameters - # @return [Smithy::Client::AuthOption] + # @return [String] def resolve(parameters) options = [] - options << Smithy::Client::AuthOption.new(scheme_id: 'smithy.api#noAuth', signer_properties: {}) + options << 'smithy.api#noAuth' options end end diff --git a/projections/shapes/lib/shapes/plugins/auth.rb b/projections/shapes/lib/shapes/plugins/auth.rb index b0b0038b3..9a4e8530d 100644 --- a/projections/shapes/lib/shapes/plugins/auth.rb +++ b/projections/shapes/lib/shapes/plugins/auth.rb @@ -50,7 +50,7 @@ def resolve_auth(context, auth_options) } auth_options.each do |auth_option| - auth_scheme = context.config.auth_schemes[auth_option.scheme_id] + auth_scheme = context.config.auth_schemes[auth_option] resolved_auth = try_load_auth_scheme( auth_option, auth_scheme, @@ -65,7 +65,7 @@ def resolve_auth(context, auth_options) end def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) - scheme_id = auth_option.scheme_id + scheme_id = auth_option unless auth_scheme failures << "Auth scheme #{scheme_id} was not enabled " \ 'for this request' @@ -79,29 +79,22 @@ def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) return end - identity_properties = auth_option.identity_properties - identity = identity_provider.identity(identity_properties) + identity = identity_provider.identity({}) ResolvedAuth.new( - scheme_id: scheme_id, identity: identity, - identity_properties: auth_option.identity_properties, - signer: auth_scheme.signer, - signer_properties: auth_option.signer_properties + signer: auth_scheme.signer ) end # @api private class ResolvedAuth def initialize(options = {}) - @scheme_id = options[:scheme_id] - @signer = options[:signer] - @signer_properties = options[:signer_properties] @identity = options[:identity] - @identity_properties = options[:identity_properties] + @signer = options[:signer] end - attr_accessor :scheme_id, :signer, :signer_properties, :identity, :identity_properties + attr_accessor :identity, :signer end end diff --git a/projections/shapes/sig/shapes/auth_resolver.rbs b/projections/shapes/sig/shapes/auth_resolver.rbs index e050dd722..013697266 100644 --- a/projections/shapes/sig/shapes/auth_resolver.rbs +++ b/projections/shapes/sig/shapes/auth_resolver.rbs @@ -1,5 +1,5 @@ module ShapeService class AuthResolver - def resolve: (AuthParameters) -> Array[Smithy::Client::AuthOption] + def resolve: (AuthParameters) -> Array[String] end end diff --git a/projections/weather/lib/weather/auth_resolver.rb b/projections/weather/lib/weather/auth_resolver.rb index 3f9e14769..a7eed4025 100644 --- a/projections/weather/lib/weather/auth_resolver.rb +++ b/projections/weather/lib/weather/auth_resolver.rb @@ -6,10 +6,10 @@ module Weather # Resolves the auth scheme from {AuthParameters}. class AuthResolver # @param [AuthParameters] parameters - # @return [Smithy::Client::AuthOption] + # @return [String] def resolve(parameters) options = [] - options << Smithy::Client::AuthOption.new(scheme_id: 'smithy.api#noAuth', signer_properties: {}) + options << 'smithy.api#noAuth' options end end diff --git a/projections/weather/lib/weather/plugins/auth.rb b/projections/weather/lib/weather/plugins/auth.rb index f3b45dc1b..2896ff7d2 100644 --- a/projections/weather/lib/weather/plugins/auth.rb +++ b/projections/weather/lib/weather/plugins/auth.rb @@ -50,7 +50,7 @@ def resolve_auth(context, auth_options) } auth_options.each do |auth_option| - auth_scheme = context.config.auth_schemes[auth_option.scheme_id] + auth_scheme = context.config.auth_schemes[auth_option] resolved_auth = try_load_auth_scheme( auth_option, auth_scheme, @@ -65,7 +65,7 @@ def resolve_auth(context, auth_options) end def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) - scheme_id = auth_option.scheme_id + scheme_id = auth_option unless auth_scheme failures << "Auth scheme #{scheme_id} was not enabled " \ 'for this request' @@ -79,29 +79,22 @@ def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) return end - identity_properties = auth_option.identity_properties - identity = identity_provider.identity(identity_properties) + identity = identity_provider.identity({}) ResolvedAuth.new( - scheme_id: scheme_id, identity: identity, - identity_properties: auth_option.identity_properties, - signer: auth_scheme.signer, - signer_properties: auth_option.signer_properties + signer: auth_scheme.signer ) end # @api private class ResolvedAuth def initialize(options = {}) - @scheme_id = options[:scheme_id] - @signer = options[:signer] - @signer_properties = options[:signer_properties] @identity = options[:identity] - @identity_properties = options[:identity_properties] + @signer = options[:signer] end - attr_accessor :scheme_id, :signer, :signer_properties, :identity, :identity_properties + attr_accessor :identity, :signer end end diff --git a/projections/weather/sig/weather/auth_resolver.rbs b/projections/weather/sig/weather/auth_resolver.rbs index 1a1009086..a41a4619c 100644 --- a/projections/weather/sig/weather/auth_resolver.rbs +++ b/projections/weather/sig/weather/auth_resolver.rbs @@ -1,5 +1,5 @@ module Weather class AuthResolver - def resolve: (AuthParameters) -> Array[Smithy::Client::AuthOption] + def resolve: (AuthParameters) -> Array[String] end end From 42917bb1465a49e66db6136288d04d6c979046b6 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 19 Jun 2025 14:04:43 -0700 Subject: [PATCH 05/19] Fix tests --- .../smithy-client/lib/smithy-client/signers/http_api_key.rb | 6 +++--- gems/smithy-client/lib/smithy-client/signers/http_basic.rb | 2 +- gems/smithy-client/lib/smithy-client/signers/http_bearer.rb | 2 +- .../spec/smithy-client/plugins/checksum_required_spec.rb | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb index de3adec8a..c19c6d68a 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb @@ -6,10 +6,10 @@ module Signers # A signer that signs requests using the HTTP API Key Auth scheme. class HttpApiKey < Signer def sign(context) - request = context.request + request = context.http_request identity = context[:auth].identity - location = context.config.service.traits['smithy.api#httpApiKeyAuth']['in'] - case location + properties = context.config.service.traits['smithy.api#httpApiKeyAuth'] + case properties['in'] when 'header' value = "#{properties['scheme']} #{identity.key}".strip request.headers[properties['name']] = value diff --git a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb index dbb64bed5..1058ce247 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb @@ -11,7 +11,7 @@ def sign(context) # TODO: does not handle realm or other properties identity_string = "#{context[:auth].identity.username}:#{context[:auth].identity.password}" encoded = Base64.strict_encode64(identity_string) - context.request.headers['Authorization'] = "Basic #{encoded}" + context.http_request.headers['Authorization'] = "Basic #{encoded}" end def reset(request:, **_options) diff --git a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb index d102c1994..4b397514c 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb @@ -7,7 +7,7 @@ module Signers class HttpBearer < Signer def sign(context) # TODO: does not handle realm or other properties - context.request.headers['Authorization'] = "Bearer #{context[:auth].identity.token}" + context.http_request.headers['Authorization'] = "Bearer #{context[:auth].identity.token}" end def reset(request:, **_options) diff --git a/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb index 29fb55926..9f72582b1 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb @@ -44,9 +44,9 @@ module Plugins it 'calculates checksums before signing' do signer = Signers::Anonymous.new - expect(signer).to receive(:sign).and_wrap_original do |method, **args| - expect(args[:request].headers['Content-Md5']).to_not be_nil - method.call(**args) + expect(signer).to receive(:sign).and_wrap_original do |method, context| + expect(context.http_request.headers['Content-Md5']).to_not be_nil + method.call(context) end auth_scheme = AuthSchemes::Anonymous.new(signer: signer) client = client_class.new(stub_responses: true, anonymous_auth_scheme: auth_scheme) From 391224484f842eefc0bf5e5280d35e76edcd87e3 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 19 Jun 2025 14:14:39 -0700 Subject: [PATCH 06/19] Fix rubocop --- gems/smithy-client/lib/smithy-client/signers/http_api_key.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb index c19c6d68a..70ed2df71 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb @@ -5,6 +5,7 @@ module Client module Signers # A signer that signs requests using the HTTP API Key Auth scheme. class HttpApiKey < Signer + # rubocop:disable Metrics/AbcSize def sign(context) request = context.http_request identity = context[:auth].identity @@ -18,6 +19,7 @@ def sign(context) append_query_param(request, name, identity.key) end end + # rubocop:enable Metrics/AbcSize def reset(request:, properties:) case properties['in'] From 707f3f9d3d4ac84ec070748542ce8fec340d0358 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 20 Jun 2025 11:41:17 -0700 Subject: [PATCH 07/19] Remove ResolvedAuth and add auth to context --- .../lib/smithy-client/handler_context.rb | 5 +++++ .../lib/smithy-client/plugins/sign_requests.rb | 2 +- .../lib/smithy-client/signers/http_api_key.rb | 2 +- .../lib/smithy-client/signers/http_basic.rb | 3 ++- .../lib/smithy-client/signers/http_bearer.rb | 2 +- .../sig/smithy-client/handler_context.rbs | 1 + .../lib/smithy/templates/client/auth_plugin.erb | 17 ++++------------- 7 files changed, 15 insertions(+), 17 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/handler_context.rb b/gems/smithy-client/lib/smithy-client/handler_context.rb index c03d35a27..22212c453 100644 --- a/gems/smithy-client/lib/smithy-client/handler_context.rb +++ b/gems/smithy-client/lib/smithy-client/handler_context.rb @@ -11,6 +11,7 @@ class HandlerContext # @option options [Configuration] :config (nil) # @option options [HTTP::Request] :http_request (HTTP::Request.new) # @option options [HTTP::Response] :http_response (HTTP::Response.new) + # @option options [Hash] :auth (nil) # @option options [Hash] :metadata ({}) def initialize(options = {}) @operation_name = options[:operation_name] @@ -20,6 +21,7 @@ def initialize(options = {}) @config = options[:config] @http_request = options[:http_request] || HTTP::Request.new @http_response = options[:http_response] || HTTP::Response.new + @auth = options[:auth] @retries = 0 @metadata = {} end @@ -45,6 +47,9 @@ def initialize(options = {}) # @return [HTTP::Response] attr_accessor :http_response + # @return [Hash] + attr_accessor :auth + # @return [Integer] attr_accessor :retries diff --git a/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb b/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb index acd4760a0..38fa9f7e4 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/sign_requests.rb @@ -8,7 +8,7 @@ class SignRequests < Plugin # @api private class Handler < Client::Handler def call(context) - context[:auth].signer.sign(context) + context.auth[:signer].sign(context) @handler.call(context) end end diff --git a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb index 70ed2df71..f446dc227 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb @@ -8,7 +8,7 @@ class HttpApiKey < Signer # rubocop:disable Metrics/AbcSize def sign(context) request = context.http_request - identity = context[:auth].identity + identity = context.auth[:identity].identity properties = context.config.service.traits['smithy.api#httpApiKeyAuth'] case properties['in'] when 'header' diff --git a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb index 1058ce247..97369596d 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb @@ -9,7 +9,8 @@ module Signers class HttpBasic < Signer def sign(context) # TODO: does not handle realm or other properties - identity_string = "#{context[:auth].identity.username}:#{context[:auth].identity.password}" + identity = context.auth[:identity] + identity_string = "#{identity.username}:#{identity.password}" encoded = Base64.strict_encode64(identity_string) context.http_request.headers['Authorization'] = "Basic #{encoded}" end diff --git a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb index 4b397514c..ab03cff69 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb @@ -7,7 +7,7 @@ module Signers class HttpBearer < Signer def sign(context) # TODO: does not handle realm or other properties - context.http_request.headers['Authorization'] = "Bearer #{context[:auth].identity.token}" + context.http_request.headers['Authorization'] = "Bearer #{context.auth[:identity].token}" end def reset(request:, **_options) diff --git a/gems/smithy-client/sig/smithy-client/handler_context.rbs b/gems/smithy-client/sig/smithy-client/handler_context.rbs index 3ab425591..34eff9394 100644 --- a/gems/smithy-client/sig/smithy-client/handler_context.rbs +++ b/gems/smithy-client/sig/smithy-client/handler_context.rbs @@ -9,6 +9,7 @@ module Smithy attr_accessor config: Struct[untyped]? attr_accessor http_request: HTTP::Request | untyped attr_accessor http_response: HTTP::Response | untyped + attr_accessor auth: Hash[Symbol, untyped] attr_accessor retries: Integer attr_reader metadata: Hash[untyped, untyped] def []: (untyped) -> untyped diff --git a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb index a58e0aee2..f10e3bb97 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb @@ -36,7 +36,7 @@ module <%= module_name %> # TODO: apply endpoint auth properties if present auth_params = AuthParameters.create(context) auth_options = context.config.auth_resolver.resolve(auth_params) - context[:auth] = resolve_auth(context, auth_options) + context.auth = resolve_auth(context, auth_options) @handler.call(context) end @@ -85,20 +85,11 @@ module <%= module_name %> identity = identity_provider.identity({}) - ResolvedAuth.new( + { + scheme_id: scheme_id, identity: identity, signer: auth_scheme.signer - ) - end - - # @api private - class ResolvedAuth - def initialize(options = {}) - @identity = options[:identity] - @signer = options[:signer] - end - - attr_accessor :identity, :signer + } end end From 2e7bee56d312645ee9e42d8a98e04df54f5c554e Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 20 Jun 2025 12:08:39 -0700 Subject: [PATCH 08/19] Fix tests and rubocop --- gems/smithy-cbor/lib/smithy-cbor/decoder.rb | 2 +- gems/smithy-client/lib/smithy-client/signers/http_api_key.rb | 2 +- gems/smithy-client/lib/smithy-client/util.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gems/smithy-cbor/lib/smithy-cbor/decoder.rb b/gems/smithy-cbor/lib/smithy-cbor/decoder.rb index 87b5df269..167b86bff 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/decoder.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/decoder.rb @@ -171,7 +171,7 @@ def read_bignum(tag_value) end end - def read_boolean # rubocop:disable Naming/PredicateMethod + def read_boolean _major_type, add_info = read_info case add_info when 20 then false diff --git a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb index f446dc227..df10b40b5 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb @@ -8,7 +8,7 @@ class HttpApiKey < Signer # rubocop:disable Metrics/AbcSize def sign(context) request = context.http_request - identity = context.auth[:identity].identity + identity = context.auth[:identity] properties = context.config.service.traits['smithy.api#httpApiKeyAuth'] case properties['in'] when 'header' diff --git a/gems/smithy-client/lib/smithy-client/util.rb b/gems/smithy-client/lib/smithy-client/util.rb index 6f3c4f6c3..b8968b148 100644 --- a/gems/smithy-client/lib/smithy-client/util.rb +++ b/gems/smithy-client/lib/smithy-client/util.rb @@ -4,7 +4,7 @@ module Smithy module Client # @api private module Util - def self.str_to_bool(str) # rubocop:disable Naming/PredicateMethod + def self.str_to_bool(str) case str when 'true' then true when 'false' then false From 827418a117bcda5ef962b829bab5f0a13bc53cc9 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 20 Jun 2025 13:25:43 -0700 Subject: [PATCH 09/19] Add retry and remove render auth option --- .../lib/smithy-client/signers/anonymous.rb | 2 +- .../lib/smithy-client/signers/http_api_key.rb | 7 ++++++- .../lib/smithy-client/signers/http_basic.rb | 5 +++-- .../lib/smithy-client/signers/http_bearer.rb | 5 +++-- .../lib/smithy-client/signers/http_digest.rb | 2 +- gems/smithy/lib/smithy/views/client/auth_resolver.rb | 10 +++------- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/signers/anonymous.rb b/gems/smithy-client/lib/smithy-client/signers/anonymous.rb index a29c756cf..49ce05855 100644 --- a/gems/smithy-client/lib/smithy-client/signers/anonymous.rb +++ b/gems/smithy-client/lib/smithy-client/signers/anonymous.rb @@ -6,7 +6,7 @@ module Signers # A signer that does not sign requests. class Anonymous < Signer def sign(context); end - def reset(**); end + def reset(context); end end end end diff --git a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb index df10b40b5..a657d4d64 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb @@ -7,6 +7,7 @@ module Signers class HttpApiKey < Signer # rubocop:disable Metrics/AbcSize def sign(context) + reset(context) request = context.http_request identity = context.auth[:identity] properties = context.config.service.traits['smithy.api#httpApiKeyAuth'] @@ -21,7 +22,9 @@ def sign(context) end # rubocop:enable Metrics/AbcSize - def reset(request:, properties:) + def reset(context) + request = context.http_request + properties = context.config.service.traits['smithy.api#httpApiKeyAuth'] case properties['in'] when 'header' request.headers.delete(properties['name']) @@ -42,6 +45,8 @@ def append_query_param(request, name, value) end def remove_query_param(request, name) + return unless request.endpoint.query + parsed = CGI.parse(request.endpoint.query) parsed.delete(name) # encode_www_form ignores query params without values diff --git a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb index 97369596d..b91fdf8a3 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_basic.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_basic.rb @@ -8,6 +8,7 @@ module Signers # A signer that signs requests using the HTTP Basic Auth scheme. class HttpBasic < Signer def sign(context) + reset(context) # TODO: does not handle realm or other properties identity = context.auth[:identity] identity_string = "#{identity.username}:#{identity.password}" @@ -15,8 +16,8 @@ def sign(context) context.http_request.headers['Authorization'] = "Basic #{encoded}" end - def reset(request:, **_options) - request.headers.delete('Authorization') + def reset(context) + context.http_request.headers.delete('Authorization') end end end diff --git a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb index ab03cff69..65ea57e67 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_bearer.rb @@ -6,12 +6,13 @@ module Signers # A signer that signs requests using the HTTP Bearer Auth scheme. class HttpBearer < Signer def sign(context) + reset(context) # TODO: does not handle realm or other properties context.http_request.headers['Authorization'] = "Bearer #{context.auth[:identity].token}" end - def reset(request:, **_options) - request.headers.delete('Authorization') + def reset(context) + context.http_request.headers.delete('Authorization') end end end diff --git a/gems/smithy-client/lib/smithy-client/signers/http_digest.rb b/gems/smithy-client/lib/smithy-client/signers/http_digest.rb index 08852b5ee..13b52018d 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_digest.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_digest.rb @@ -12,7 +12,7 @@ def sign(context) raise NotImplementedError end - def reset(request:, **_options) + def reset(context) raise NotImplementedError end end diff --git a/gems/smithy/lib/smithy/views/client/auth_resolver.rb b/gems/smithy/lib/smithy/views/client/auth_resolver.rb index e074a3398..921412da1 100644 --- a/gems/smithy/lib/smithy/views/client/auth_resolver.rb +++ b/gems/smithy/lib/smithy/views/client/auth_resolver.rb @@ -26,7 +26,7 @@ def auth_rules_code auth_operations = operations_with_auth_traits if auth_operations.empty? service_auth_schemes.each do |auth_scheme| - lines << "options << #{render_auth_option(auth_scheme)}" + lines << "options << #{auth_scheme}" end else lines << 'case parameters.operation_name' @@ -34,12 +34,12 @@ def auth_rules_code operation_name = Model::Shape.name(id).underscore lines << "when :#{operation_name}" operation_auth_schemes(operation).each do |auth_scheme| - lines << " options << #{render_auth_option(auth_scheme)}" + lines << " options << #{auth_scheme}" end end lines << 'else' service_auth_schemes.each do |auth_scheme| - lines << " options << #{render_auth_option(auth_scheme)}" + lines << " options << #{auth_scheme}" end lines << 'end' end @@ -114,10 +114,6 @@ def add_registered_auth_schemes(auth_schemes, traits) auth_schemes << auth_scheme if traits.key?(auth_scheme) end end - - def render_auth_option(auth_scheme) - "'#{auth_scheme}'" - end end end end From ad97d91b39ab5bf343f55b36d3b7e68a26cdd335 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 20 Jun 2025 13:39:18 -0700 Subject: [PATCH 10/19] Add quotes --- gems/smithy/lib/smithy/views/client/auth_resolver.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gems/smithy/lib/smithy/views/client/auth_resolver.rb b/gems/smithy/lib/smithy/views/client/auth_resolver.rb index 921412da1..1677853f7 100644 --- a/gems/smithy/lib/smithy/views/client/auth_resolver.rb +++ b/gems/smithy/lib/smithy/views/client/auth_resolver.rb @@ -26,7 +26,7 @@ def auth_rules_code auth_operations = operations_with_auth_traits if auth_operations.empty? service_auth_schemes.each do |auth_scheme| - lines << "options << #{auth_scheme}" + lines << "options << '#{auth_scheme}'" end else lines << 'case parameters.operation_name' @@ -34,12 +34,12 @@ def auth_rules_code operation_name = Model::Shape.name(id).underscore lines << "when :#{operation_name}" operation_auth_schemes(operation).each do |auth_scheme| - lines << " options << #{auth_scheme}" + lines << " options << '#{auth_scheme}'" end end lines << 'else' service_auth_schemes.each do |auth_scheme| - lines << " options << #{auth_scheme}" + lines << " options << '#{auth_scheme}'" end lines << 'end' end From 4c8b28a5d972328fe6cf263b2450a9566aec95a3 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 20 Jun 2025 14:17:44 -0700 Subject: [PATCH 11/19] Remove properties from identity --- .../lib/smithy-client/anonymous_provider.rb | 2 +- .../smithy-client/http_api_key_provider.rb | 2 +- .../lib/smithy-client/http_bearer_provider.rb | 2 +- .../lib/smithy-client/http_login_provider.rb | 2 +- .../plugins/http_api_key_auth.rb | 2 +- .../smithy-client/plugins/http_basic_auth.rb | 2 +- .../smithy-client/plugins/http_bearer_auth.rb | 2 +- .../smithy-client/plugins/http_digest_auth.rb | 2 +- .../refreshing_identity_provider.rb | 16 +++++------ .../spec/smithy-client/auth_scheme_spec.rb | 2 +- .../plugins/http_api_key_auth_spec.rb | 4 +-- .../plugins/http_basic_auth_spec.rb | 4 +-- .../plugins/http_bearer_auth_spec.rb | 4 +-- .../plugins/http_digest_auth_spec.rb | 4 +-- .../refreshing_identity_provider_spec.rb | 28 +++++++++---------- .../smithy/templates/client/auth_plugin.erb | 2 +- projections/shapes/lib/shapes/plugins/auth.rb | 2 +- .../weather/lib/weather/plugins/auth.rb | 2 +- 18 files changed, 42 insertions(+), 42 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/anonymous_provider.rb b/gems/smithy-client/lib/smithy-client/anonymous_provider.rb index a3ed9444d..4455f6006 100644 --- a/gems/smithy-client/lib/smithy-client/anonymous_provider.rb +++ b/gems/smithy-client/lib/smithy-client/anonymous_provider.rb @@ -4,7 +4,7 @@ module Smithy module Client # @api private class AnonymousProvider - def identity(_properties) + def identity Identities::Anonymous.new end end diff --git a/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb b/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb index 271aa57d1..ad79d0998 100644 --- a/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb +++ b/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb @@ -10,7 +10,7 @@ def initialize(key) end # @return [Identities::HttpApiKey] - def identity(_properties) + def identity @identity end end diff --git a/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb b/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb index 54e06bfad..f5d765049 100644 --- a/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb +++ b/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb @@ -10,7 +10,7 @@ def initialize(token) end # @return [Identities::HttpBearer] - def identity(_properties) + def identity @identity end end diff --git a/gems/smithy-client/lib/smithy-client/http_login_provider.rb b/gems/smithy-client/lib/smithy-client/http_login_provider.rb index b64fbf3c6..21af7c77b 100644 --- a/gems/smithy-client/lib/smithy-client/http_login_provider.rb +++ b/gems/smithy-client/lib/smithy-client/http_login_provider.rb @@ -11,7 +11,7 @@ def initialize(username, password) end # @return [Identities::HttpLogin] - def identity(_properties) + def identity @identity end end diff --git a/gems/smithy-client/lib/smithy-client/plugins/http_api_key_auth.rb b/gems/smithy-client/lib/smithy-client/plugins/http_api_key_auth.rb index 868ae7c1e..e310d9140 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/http_api_key_auth.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/http_api_key_auth.rb @@ -23,7 +23,7 @@ class HttpApiKeyAuth < Plugin doc_type: HttpApiKeyProvider, docstring: <<~DOCS) do |config| An API key identity provider. This can be an instance of a {Smithy::Client::HttpApiKeyProvider} or any - class that responds to #identity(properties) and returns a {Smithy::Client::Identities::HttpApiKey}. + class that responds to #identity and returns a {Smithy::Client::Identities::HttpApiKey}. DOCS HttpApiKeyProvider.new(config.http_api_key) if config.http_api_key end diff --git a/gems/smithy-client/lib/smithy-client/plugins/http_basic_auth.rb b/gems/smithy-client/lib/smithy-client/plugins/http_basic_auth.rb index db030288f..5154e2d5b 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/http_basic_auth.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/http_basic_auth.rb @@ -31,7 +31,7 @@ class HttpBasicAuth < Plugin doc_type: Smithy::Client::HttpLoginProvider, docstring: <<~DOCS) do |config| A login identity provider. This can be an instance of a {Smithy::Client::HttpLoginProvider} or any - class that responds to #identity(properties) and returns a {Smithy::Client::Identities::HttpLogin}. + class that responds to #identity and returns a {Smithy::Client::Identities::HttpLogin}. DOCS if config.http_login_username && config.http_login_password Smithy::Client::HttpLoginProvider.new(config.http_login_username, config.http_login_password) diff --git a/gems/smithy-client/lib/smithy-client/plugins/http_bearer_auth.rb b/gems/smithy-client/lib/smithy-client/plugins/http_bearer_auth.rb index 32323ba34..88bfe92c3 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/http_bearer_auth.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/http_bearer_auth.rb @@ -23,7 +23,7 @@ class HttpBearerAuth < Plugin doc_type: Smithy::Client::HttpBearerProvider, docstring: <<~DOCS) do |config| A bearer token identity provider. This can be an instance of a {Smithy::Client::HttpBearerProvider} or any - class that responds to #identity(properties) and returns a {Smithy::Client::Identities::HttpBearer}. + class that responds to #identity and returns a {Smithy::Client::Identities::HttpBearer}. DOCS Smithy::Client::HttpBearerProvider.new(config.http_bearer_token) if config.http_bearer_token end diff --git a/gems/smithy-client/lib/smithy-client/plugins/http_digest_auth.rb b/gems/smithy-client/lib/smithy-client/plugins/http_digest_auth.rb index f1d30210c..40a70f87a 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/http_digest_auth.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/http_digest_auth.rb @@ -44,7 +44,7 @@ class HttpDigestAuth < Plugin doc_type: Smithy::Client::HttpLoginProvider, docstring: <<~DOCS) do |config| A login identity provider. This can be an instance of a {Smithy::Client::HttpLoginProvider} or any - class that responds to #identity(properties) and returns a {Smithy::Client::Identities::HttpLogin}. + class that responds to #identity and returns a {Smithy::Client::Identities::HttpLogin}. DOCS if config.http_login_username && config.http_login_password Smithy::Client::HttpLoginProvider.new(config.http_login_username, config.http_login_password) diff --git a/gems/smithy-client/lib/smithy-client/refreshing_identity_provider.rb b/gems/smithy-client/lib/smithy-client/refreshing_identity_provider.rb index f3a89aa60..53ae29878 100644 --- a/gems/smithy-client/lib/smithy-client/refreshing_identity_provider.rb +++ b/gems/smithy-client/lib/smithy-client/refreshing_identity_provider.rb @@ -3,8 +3,8 @@ module Smithy module Client # A module that can be included in a class to provide a #identity method. - # The class must implement #refresh(properties) that sets @identity. The - # refresh method will be called when #identity is called and the identity + # The class must implement #refresh that sets @identity. The refresh + # method will be called when #identity is called and the identity # is nil or near expiration. module RefreshingIdentityProvider SYNC_EXPIRATION_LENGTH = 300 # 5 minutes @@ -15,11 +15,11 @@ def initialize end # @return [Identities::Base] - def identity(properties = {}) + def identity if @identity - refresh_if_near_expiration!(properties) + refresh_if_near_expiration! else # initialization - @mutex.synchronize { refresh(properties) } + @mutex.synchronize { refresh } end @identity end @@ -38,19 +38,19 @@ def async_expiration_length # If we are near to expiration, block while refreshing the identity. # Otherwise, if we're approaching expiration, use the existing identity # but attempt a refresh in the background. - def refresh_if_near_expiration!(properties) + def refresh_if_near_expiration! # NOTE: This check is an optimization. Rather than acquire the mutex on # every #refresh_if_near_expiration call, we check before doing so, and # then we check within the mutex to avoid a race condition. if near_expiration?(sync_expiration_length) @mutex.synchronize do - refresh(properties) if near_expiration?(sync_expiration_length) + refresh if near_expiration?(sync_expiration_length) end elsif @async_refresh && near_expiration?(async_expiration_length) unless @mutex.locked? Thread.new do @mutex.synchronize do - refresh(properties) if near_expiration?(async_expiration_length) + refresh if near_expiration?(async_expiration_length) end end end diff --git a/gems/smithy-client/spec/smithy-client/auth_scheme_spec.rb b/gems/smithy-client/spec/smithy-client/auth_scheme_spec.rb index 1a2f40417..e0ca26661 100644 --- a/gems/smithy-client/spec/smithy-client/auth_scheme_spec.rb +++ b/gems/smithy-client/spec/smithy-client/auth_scheme_spec.rb @@ -10,7 +10,7 @@ module Client let(:identity_type) { Identity } let(:identity_provider_class) do Class.new do - def identity(_properties) + def identity Identity.new end end diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb index 5762b1b6d..862213252 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb @@ -51,14 +51,14 @@ module Plugins it 'has a default :http_api_key_provider when :stub_responses is true' do provider = client.config.http_api_key_provider expect(provider).to be_a(HttpApiKeyProvider) - expect(provider.identity({}).key).to eq('stubbed-api-key') + expect(provider.identity.key).to eq('stubbed-api-key') end it 'defaults a :http_api_key_provider when :http_api_key is set' do client = client_class.new(http_api_key: 'api-key') provider = client.config.http_api_key_provider expect(provider).to be_a(HttpApiKeyProvider) - expect(provider.identity({}).key).to eq('api-key') + expect(provider.identity.key).to eq('api-key') end context 'signing' do diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb index a03e73a3f..3413ac694 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb @@ -57,7 +57,7 @@ module Plugins it 'has a default :http_login_provider when :stub_responses is true' do provider = client.config.http_login_provider expect(provider).to be_a(HttpLoginProvider) - identity = provider.identity({}) + identity = provider.identity expect(identity.username).to eq('stubbed-username') expect(identity.password).to eq('stubbed-password') end @@ -66,7 +66,7 @@ module Plugins client = client_class.new(http_login_username: 'username', http_login_password: 'password') provider = client.config.http_login_provider expect(provider).to be_a(HttpLoginProvider) - identity = provider.identity({}) + identity = provider.identity expect(identity.username).to eq('username') expect(identity.password).to eq('password') end diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb index 44391302d..55fb81f7d 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb @@ -51,14 +51,14 @@ module Plugins it 'has a default :http_bearer_provider when :stub_responses is true' do provider = client.config.http_bearer_provider expect(provider).to be_a(HttpBearerProvider) - expect(provider.identity({}).token).to eq('stubbed-bearer-token') + expect(provider.identity.token).to eq('stubbed-bearer-token') end it 'defaults a :http_bearer_provider when :http_bearer_token is set' do client = client_class.new(http_bearer_token: 'bearer') provider = client.config.http_bearer_provider expect(provider).to be_a(HttpBearerProvider) - expect(provider.identity({}).token).to eq('bearer') + expect(provider.identity.token).to eq('bearer') end context 'signing' do diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_digest_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_digest_auth_spec.rb index 258d23819..528f41092 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_digest_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_digest_auth_spec.rb @@ -57,7 +57,7 @@ module Plugins it 'has a default :http_login_provider when :stub_responses is true' do provider = client.config.http_login_provider expect(provider).to be_a(HttpLoginProvider) - identity = provider.identity({}) + identity = provider.identity expect(identity.username).to eq('stubbed-username') expect(identity.password).to eq('stubbed-password') end @@ -66,7 +66,7 @@ module Plugins client = client_class.new(http_login_username: 'username', http_login_password: 'password') provider = client.config.http_login_provider expect(provider).to be_a(HttpLoginProvider) - identity = provider.identity({}) + identity = provider.identity expect(identity.username).to eq('username') expect(identity.password).to eq('password') end diff --git a/gems/smithy-client/spec/smithy-client/refreshing_identity_provider_spec.rb b/gems/smithy-client/spec/smithy-client/refreshing_identity_provider_spec.rb index b1085fdc1..eb16a8925 100644 --- a/gems/smithy-client/spec/smithy-client/refreshing_identity_provider_spec.rb +++ b/gems/smithy-client/spec/smithy-client/refreshing_identity_provider_spec.rb @@ -15,8 +15,8 @@ def initialize(proc) super() end - def refresh(properties = {}) - @identity = @proc.call(properties) + def refresh + @identity = @proc.call end end end @@ -27,17 +27,17 @@ def refresh(properties = {}) end let(:properties) { { foo: 'bar' } } - let(:proc) { ->(_properties) {} } + let(:proc) { -> {} } subject { identity_resolver.new(proc) } describe '#identity' do it 'initializes the identity' do - expect(proc).to receive(:call).with(properties).and_return(refreshed_expiration_identity) - expect(subject).to receive(:refresh).with(properties).and_call_original + expect(proc).to receive(:call).and_return(refreshed_expiration_identity) + expect(subject).to receive(:refresh).and_call_original expect(subject.instance_variable_get(:@identity)).to be_nil - identity = subject.identity(properties) + identity = subject.identity expect(identity).to eq(refreshed_expiration_identity) expect(subject.instance_variable_get(:@identity)).to eq(identity) end @@ -51,13 +51,13 @@ def refresh(properties = {}) it 'refreshes synchronously' do expect(Thread).not_to receive(:new) expect(proc).to receive(:call) - .with(properties).and_return(near_sync_expiration_identity) + .and_return(near_sync_expiration_identity) expect(proc).to receive(:call) - .with(properties).and_return(refreshed_expiration_identity) + .and_return(refreshed_expiration_identity) - identity = subject.identity(properties) # initialize + identity = subject.identity # initialize expect(identity).to eq(near_sync_expiration_identity) - identity = subject.identity(properties) # refreshing + identity = subject.identity # refreshing expect(identity).to eq(refreshed_expiration_identity) end end @@ -71,12 +71,12 @@ def refresh(properties = {}) it 'refreshes asynchronously' do expect(Thread).to receive(:new).and_yield expect(proc).to receive(:call) - .with(properties).and_return(near_async_expiration_identity) + .and_return(near_async_expiration_identity) expect(proc).to receive(:call) - .with(properties).and_return(refreshed_expiration_identity) - identity = subject.identity(properties) # initialize + .and_return(refreshed_expiration_identity) + identity = subject.identity # initialize expect(identity).to eq(near_async_expiration_identity) - identity = subject.identity(properties) # refreshing + identity = subject.identity # refreshing expect(identity).to eq(refreshed_expiration_identity) end end diff --git a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb index f10e3bb97..c40d89b97 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb @@ -83,7 +83,7 @@ module <%= module_name %> return end - identity = identity_provider.identity({}) + identity = identity_provider.identity { scheme_id: scheme_id, diff --git a/projections/shapes/lib/shapes/plugins/auth.rb b/projections/shapes/lib/shapes/plugins/auth.rb index 9a4e8530d..a3f3bf7db 100644 --- a/projections/shapes/lib/shapes/plugins/auth.rb +++ b/projections/shapes/lib/shapes/plugins/auth.rb @@ -79,7 +79,7 @@ def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) return end - identity = identity_provider.identity({}) + identity = identity_provider.identity ResolvedAuth.new( identity: identity, diff --git a/projections/weather/lib/weather/plugins/auth.rb b/projections/weather/lib/weather/plugins/auth.rb index 2896ff7d2..1bdcfcb41 100644 --- a/projections/weather/lib/weather/plugins/auth.rb +++ b/projections/weather/lib/weather/plugins/auth.rb @@ -79,7 +79,7 @@ def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) return end - identity = identity_provider.identity({}) + identity = identity_provider.identity ResolvedAuth.new( identity: identity, From 2e1d8c5d31cc65da7058fb9b16827421b4170eea Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 20 Jun 2025 14:21:17 -0700 Subject: [PATCH 12/19] Rubocop --- gems/smithy-client/lib/smithy-client/http_api_key_provider.rb | 4 +--- gems/smithy-client/lib/smithy-client/http_bearer_provider.rb | 4 +--- gems/smithy-client/lib/smithy-client/http_login_provider.rb | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb b/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb index ad79d0998..d37794f84 100644 --- a/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb +++ b/gems/smithy-client/lib/smithy-client/http_api_key_provider.rb @@ -10,9 +10,7 @@ def initialize(key) end # @return [Identities::HttpApiKey] - def identity - @identity - end + attr_reader :identity end end end diff --git a/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb b/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb index f5d765049..5c9934acf 100644 --- a/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb +++ b/gems/smithy-client/lib/smithy-client/http_bearer_provider.rb @@ -10,9 +10,7 @@ def initialize(token) end # @return [Identities::HttpBearer] - def identity - @identity - end + attr_reader :identity end end end diff --git a/gems/smithy-client/lib/smithy-client/http_login_provider.rb b/gems/smithy-client/lib/smithy-client/http_login_provider.rb index 21af7c77b..2b8c52001 100644 --- a/gems/smithy-client/lib/smithy-client/http_login_provider.rb +++ b/gems/smithy-client/lib/smithy-client/http_login_provider.rb @@ -11,9 +11,7 @@ def initialize(username, password) end # @return [Identities::HttpLogin] - def identity - @identity - end + attr_reader :identity end end end From 9be35ff995fcb6eabf35a7e377192a46b0f92435 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 23 Jun 2025 13:26:23 -0700 Subject: [PATCH 13/19] Refactor auth handler --- .../lib/smithy-client/plugins/auth.rb | 68 +++++++++++++++++++ .../smithy/templates/client/auth_plugin.erb | 65 ------------------ .../smithy/templates/client/auth_resolver.erb | 5 +- .../templates/client/auth_resolver_rbs.erb | 2 +- .../lib/smithy/templates/client/client.erb | 10 +++ .../lib/smithy/views/client/auth_plugin.rb | 4 -- gems/smithy/lib/smithy/views/client/client.rb | 10 +++ gems/smithy/lib/smithy/welds/plugins.rb | 2 + 8 files changed, 94 insertions(+), 72 deletions(-) create mode 100644 gems/smithy-client/lib/smithy-client/plugins/auth.rb diff --git a/gems/smithy-client/lib/smithy-client/plugins/auth.rb b/gems/smithy-client/lib/smithy-client/plugins/auth.rb new file mode 100644 index 000000000..af20ae57a --- /dev/null +++ b/gems/smithy-client/lib/smithy-client/plugins/auth.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +module Smithy + module Client + module Plugins + # @api private + class Auth < Plugin + # @api private + class Handler < Smithy::Client::Handler + def call(context) + # TODO: apply endpoint auth properties if present + auth_options = context.config.auth_resolver.resolve(context) + context.auth = resolve_auth(context, auth_options) + @handler.call(context) + end + + private + + def resolve_auth(context, auth_options) + failures = [] + + raise 'No auth options were resolved' if auth_options.empty? + + identity_providers = context.client.class.identity_providers(context) + + auth_options.each do |auth_option| + auth_scheme = context.config.auth_schemes[auth_option] + resolved_auth = try_load_auth_scheme( + auth_option, + auth_scheme, + identity_providers, + failures + ) + + return resolved_auth if resolved_auth + end + + raise failures.join("\n") + end + + def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) + scheme_id = auth_option + unless auth_scheme + failures << "Auth scheme #{scheme_id} was not enabled " \ + 'for this request' + return + end + + identity_provider = auth_scheme.identity_provider(identity_providers) + unless identity_provider + failures << "Auth scheme #{scheme_id} did not have an " \ + 'identity resolver configured' + return + end + + { + scheme_id: scheme_id, + identity: identity_provider.identity, + signer: auth_scheme.signer + } + end + end + + handler(Handler, step: :sign, priority: 70) + end + end + end +end \ No newline at end of file diff --git a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb index c40d89b97..f0813f34d 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb @@ -29,71 +29,6 @@ module <%= module_name %> <% end -%> } end - - # @api private - class Handler < Smithy::Client::Handler - def call(context) - # TODO: apply endpoint auth properties if present - auth_params = AuthParameters.create(context) - auth_options = context.config.auth_resolver.resolve(auth_params) - context.auth = resolve_auth(context, auth_options) - @handler.call(context) - end - - private - - def resolve_auth(context, auth_options) - failures = [] - - raise 'No auth options were resolved' if auth_options.empty? - - identity_providers = { -<% identity_providers.each do |k, v| -%> - <%= k %> => context.config.<%= v %>, -<% end -%> - } - - auth_options.each do |auth_option| - auth_scheme = context.config.auth_schemes[auth_option] - resolved_auth = try_load_auth_scheme( - auth_option, - auth_scheme, - identity_providers, - failures - ) - - return resolved_auth if resolved_auth - end - - raise failures.join("\n") - end - - def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) - scheme_id = auth_option - unless auth_scheme - failures << "Auth scheme #{scheme_id} was not enabled " \ - 'for this request' - return - end - - identity_provider = auth_scheme.identity_provider(identity_providers) - unless identity_provider - failures << "Auth scheme #{scheme_id} did not have an " \ - 'identity resolver configured' - return - end - - identity = identity_provider.identity - - { - scheme_id: scheme_id, - identity: identity, - signer: auth_scheme.signer - } - end - end - - handler(Handler, step: :sign, priority: 70) end end end diff --git a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb index 4d1545d85..b97e33c06 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_resolver.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_resolver.erb @@ -5,9 +5,10 @@ module <%= module_name %> # Resolves the auth scheme from {AuthParameters}. class AuthResolver - # @param [AuthParameters] parameters + # @param [HandlerContext] context # @return [String] - def resolve(parameters) + def resolve(context) + parameters = AuthParameters.create(context) <% auth_rules_code.each do |line| -%> <%= line %> <% end -%> diff --git a/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb b/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb index 317925dd6..b245bdd1e 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb @@ -1,5 +1,5 @@ module <%= module_name %> class AuthResolver - def resolve: (AuthParameters) -> Array[String] + def resolve: (HandlerContext) -> Array[String] end end diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index c228b2702..b5120fa4e 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -132,6 +132,16 @@ module <%= module_name %> <%= protocols %> end + + # @api private + def identity_providers(context) + { +<% identity_providers.each do |k, v| -%> + <%= k %> => context.config.<%= v %>, +<% end -%> + } + end + # @api private def errors_module Errors diff --git a/gems/smithy/lib/smithy/views/client/auth_plugin.rb b/gems/smithy/lib/smithy/views/client/auth_plugin.rb index 0e74d47d8..28d9c3a74 100644 --- a/gems/smithy/lib/smithy/views/client/auth_plugin.rb +++ b/gems/smithy/lib/smithy/views/client/auth_plugin.rb @@ -19,10 +19,6 @@ def auth_schemes @auth_schemes.transform_values { |v| v[:auth_scheme_config_option] } end - def identity_providers - @auth_schemes.to_h { |_, v| [v[:identity_type], v[:identity_provider_config_option]] } - end - private def weld_auth_schemes(welds) diff --git a/gems/smithy/lib/smithy/views/client/client.rb b/gems/smithy/lib/smithy/views/client/client.rb index b41965b76..73a277b51 100644 --- a/gems/smithy/lib/smithy/views/client/client.rb +++ b/gems/smithy/lib/smithy/views/client/client.rb @@ -67,6 +67,11 @@ def protocols @protocols ||= @plan.welds.map(&:protocols).reduce({}, :merge) end + def identity_providers + auth_schemes = weld_auth_schemes(@plan.welds) + auth_schemes.to_h { |_, v| [v[:identity_type], v[:identity_provider_config_option]] } + end + def waiters waiters = Views::Client::Waiters.new(@plan).waiters return ['{}'] if waiters.empty? @@ -107,6 +112,11 @@ def option_default(option) default.gsub('', protocols.keys.first || 'nil') end + def weld_auth_schemes(welds) + weld_auth_schemes = welds.map(&:add_auth_schemes).reduce({}, :merge) + weld_auth_schemes.except(*welds.map(&:remove_auth_schemes).reduce([], :+)) + end + # @api private class Operation def initialize(service, model, id, operation) diff --git a/gems/smithy/lib/smithy/welds/plugins.rb b/gems/smithy/lib/smithy/welds/plugins.rb index 3943b5efd..858f3549a 100644 --- a/gems/smithy/lib/smithy/welds/plugins.rb +++ b/gems/smithy/lib/smithy/welds/plugins.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require 'smithy-client/plugins/auth' require 'smithy-client/plugins/checksum_required' require 'smithy-client/plugins/content_length' require 'smithy-client/plugins/default_params' @@ -30,6 +31,7 @@ def for?(_service) def add_plugins base_path = 'smithy-client/plugins' { + Smithy::Client::Plugins::Auth => { require_path: "#{base_path}/auth" }, Smithy::Client::Plugins::ChecksumRequired => { require_path: "#{base_path}/checksum_required" }, Smithy::Client::Plugins::ContentLength => { require_path: "#{base_path}/content_length" }, Smithy::Client::Plugins::DefaultParams => { require_path: "#{base_path}/default_params" }, From 0d1c508193c6f0b5d35fd87ec1b2660832b01c04 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 23 Jun 2025 13:43:35 -0700 Subject: [PATCH 14/19] Fix tests --- .../spec/smithy-client/plugins/checksum_required_spec.rb | 1 + .../spec/smithy-client/plugins/http_api_key_auth_spec.rb | 1 + .../spec/smithy-client/plugins/http_basic_auth_spec.rb | 1 + .../spec/smithy-client/plugins/http_bearer_auth_spec.rb | 1 + 4 files changed, 4 insertions(+) diff --git a/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb index ac27c83b3..08a43adc2 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb @@ -17,6 +17,7 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) + client_class.add_plugin(Auth) client_class.add_plugin(ChecksumRequired) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb index 4380b391c..e10933bfb 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb @@ -17,6 +17,7 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) + client_class.add_plugin(Auth) client_class.add_plugin(HttpApiKeyAuth) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb index a502160e8..fbd8486c5 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb @@ -17,6 +17,7 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) + client_class.add_plugin(Auth) client_class.add_plugin(HttpBasicAuth) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb index aa5af8816..cbd99ac6f 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb @@ -17,6 +17,7 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) + client_class.add_plugin(Auth) client_class.add_plugin(HttpBearerAuth) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) From 0aafa567cb1e3e2ff6892f07d0edc67483dbd78d Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 23 Jun 2025 14:54:49 -0700 Subject: [PATCH 15/19] Update rbs interface --- gems/smithy-client/sig/smithy-client/interfaces.rbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/smithy-client/sig/smithy-client/interfaces.rbs b/gems/smithy-client/sig/smithy-client/interfaces.rbs index 9167ee7f3..ed0a2a5d8 100644 --- a/gems/smithy-client/sig/smithy-client/interfaces.rbs +++ b/gems/smithy-client/sig/smithy-client/interfaces.rbs @@ -3,7 +3,7 @@ module Smithy type endpoint_url = String | URI::HTTP | URI::HTTPS interface _IdentityProvider - def identity: (Hash[untyped, untyped] properties) -> Identity + def identity: () -> Identity end interface _ReadableIO From 1d844c458647ac3f3d05ce4df43a9cfe72f23db8 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 24 Jun 2025 08:57:36 -0700 Subject: [PATCH 16/19] Fix rbs for auth resolver --- .../templates/client/auth_resolver_rbs.erb | 2 +- .../interfaces/client/auth_resolver_spec.rb | 20 +++--- .../shapes/lib/shapes/auth_resolver.rb | 5 +- projections/shapes/lib/shapes/client.rb | 10 +++ projections/shapes/lib/shapes/plugins/auth.rb | 72 ------------------- .../shapes/sig/shapes/auth_resolver.rbs | 2 +- .../weather/lib/weather/auth_resolver.rb | 5 +- projections/weather/lib/weather/client.rb | 10 +++ .../weather/lib/weather/plugins/auth.rb | 72 ------------------- .../weather/sig/weather/auth_resolver.rbs | 2 +- 10 files changed, 39 insertions(+), 161 deletions(-) diff --git a/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb b/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb index b245bdd1e..5ed256110 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_resolver_rbs.erb @@ -1,5 +1,5 @@ module <%= module_name %> class AuthResolver - def resolve: (HandlerContext) -> Array[String] + def resolve: (Smithy::Client::HandlerContext) -> Array[String] end end diff --git a/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb b/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb index 2ca811ab5..bb8bc8ded 100644 --- a/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb +++ b/gems/smithy/spec/interfaces/client/auth_resolver_spec.rb @@ -13,15 +13,15 @@ describe '#resolve' do it 'returns the auth options alphabetically by default' do - params = NoAuthTrait::AuthParameters.new(operation_name: :operation_a) - auth_options = subject.resolve(params) + context = Smithy::Client::HandlerContext.new(operation_name: :operation_a) + auth_options = subject.resolve(context) expected = %w[smithy.api#httpBasicAuth smithy.api#httpBearerAuth smithy.api#httpDigestAuth] expect(auth_options).to eq(expected) end it 'returns the auth options for the operation with the auth trait' do - params = NoAuthTrait::AuthParameters.new(operation_name: :operation_b) - auth_options = subject.resolve(params) + context = Smithy::Client::HandlerContext.new(operation_name: :operation_b) + auth_options = subject.resolve(context) expect(auth_options).to eq(['smithy.api#httpDigestAuth']) end end @@ -34,21 +34,21 @@ describe '#resolve' do it 'returns the auth options with the service auth trait' do - params = AuthTrait::AuthParameters.new(operation_name: :operation_c) - auth_options = subject.resolve(params) + context = Smithy::Client::HandlerContext.new(operation_name: :operation_c) + auth_options = subject.resolve(context) expected = %w[smithy.api#httpBasicAuth smithy.api#httpDigestAuth] expect(auth_options).to eq(expected) end it 'returns the auth options for the operation overriding the service auth trait' do - params = AuthTrait::AuthParameters.new(operation_name: :operation_d) - auth_options = subject.resolve(params) + context = Smithy::Client::HandlerContext.new(operation_name: :operation_d) + auth_options = subject.resolve(context) expect(auth_options).to eq(['smithy.api#httpBearerAuth']) end it 'returns a noAuth option when the auth trait is empty' do - params = AuthTrait::AuthParameters.new(operation_name: :operation_e) - auth_options = subject.resolve(params) + context = Smithy::Client::HandlerContext.new(operation_name: :operation_e) + auth_options = subject.resolve(context) expect(auth_options).to eq(['smithy.api#noAuth']) end end diff --git a/projections/shapes/lib/shapes/auth_resolver.rb b/projections/shapes/lib/shapes/auth_resolver.rb index bad636518..4e84e0f01 100644 --- a/projections/shapes/lib/shapes/auth_resolver.rb +++ b/projections/shapes/lib/shapes/auth_resolver.rb @@ -5,9 +5,10 @@ module ShapeService # Resolves the auth scheme from {AuthParameters}. class AuthResolver - # @param [AuthParameters] parameters + # @param [HandlerContext] context # @return [String] - def resolve(parameters) + def resolve(context) + parameters = AuthParameters.create(context) options = [] options << 'smithy.api#noAuth' options diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 4d521a4a4..055e658c0 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -4,6 +4,7 @@ require_relative 'plugins/auth' require_relative 'plugins/endpoint' +require 'smithy-client/plugins/auth' require 'smithy-client/plugins/checksum_required' require 'smithy-client/plugins/content_length' require 'smithy-client/plugins/default_params' @@ -33,6 +34,7 @@ class Client < Smithy::Client::Base add_plugin(::ShapeService::Plugins::Auth) add_plugin(::ShapeService::Plugins::Endpoint) + add_plugin(Smithy::Client::Plugins::Auth) add_plugin(Smithy::Client::Plugins::ChecksumRequired) add_plugin(Smithy::Client::Plugins::ContentLength) add_plugin(Smithy::Client::Plugins::DefaultParams) @@ -361,6 +363,14 @@ def protocols {} end + + # @api private + def identity_providers(context) + { + Smithy::Client::Identities::Anonymous => context.config.anonymous_provider, + } + end + # @api private def errors_module Errors diff --git a/projections/shapes/lib/shapes/plugins/auth.rb b/projections/shapes/lib/shapes/plugins/auth.rb index a3f3bf7db..bd3827efc 100644 --- a/projections/shapes/lib/shapes/plugins/auth.rb +++ b/projections/shapes/lib/shapes/plugins/auth.rb @@ -27,78 +27,6 @@ class Auth < Smithy::Client::Plugin 'smithy.api#noAuth' => config.anonymous_auth_scheme, } end - - # @api private - class Handler < Smithy::Client::Handler - def call(context) - # TODO: apply endpoint auth properties if present - auth_params = AuthParameters.create(context) - auth_options = context.config.auth_resolver.resolve(auth_params) - context[:auth] = resolve_auth(context, auth_options) - @handler.call(context) - end - - private - - def resolve_auth(context, auth_options) - failures = [] - - raise 'No auth options were resolved' if auth_options.empty? - - identity_providers = { - Smithy::Client::Identities::Anonymous => context.config.anonymous_provider, - } - - auth_options.each do |auth_option| - auth_scheme = context.config.auth_schemes[auth_option] - resolved_auth = try_load_auth_scheme( - auth_option, - auth_scheme, - identity_providers, - failures - ) - - return resolved_auth if resolved_auth - end - - raise failures.join("\n") - end - - def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) - scheme_id = auth_option - unless auth_scheme - failures << "Auth scheme #{scheme_id} was not enabled " \ - 'for this request' - return - end - - identity_provider = auth_scheme.identity_provider(identity_providers) - unless identity_provider - failures << "Auth scheme #{scheme_id} did not have an " \ - 'identity resolver configured' - return - end - - identity = identity_provider.identity - - ResolvedAuth.new( - identity: identity, - signer: auth_scheme.signer - ) - end - - # @api private - class ResolvedAuth - def initialize(options = {}) - @identity = options[:identity] - @signer = options[:signer] - end - - attr_accessor :identity, :signer - end - end - - handler(Handler, step: :sign, priority: 70) end end end diff --git a/projections/shapes/sig/shapes/auth_resolver.rbs b/projections/shapes/sig/shapes/auth_resolver.rbs index 013697266..c7141157b 100644 --- a/projections/shapes/sig/shapes/auth_resolver.rbs +++ b/projections/shapes/sig/shapes/auth_resolver.rbs @@ -1,5 +1,5 @@ module ShapeService class AuthResolver - def resolve: (AuthParameters) -> Array[String] + def resolve: (?Hash[Symbol, untyped]) -> Array[String] end end diff --git a/projections/weather/lib/weather/auth_resolver.rb b/projections/weather/lib/weather/auth_resolver.rb index a7eed4025..7e158383e 100644 --- a/projections/weather/lib/weather/auth_resolver.rb +++ b/projections/weather/lib/weather/auth_resolver.rb @@ -5,9 +5,10 @@ module Weather # Resolves the auth scheme from {AuthParameters}. class AuthResolver - # @param [AuthParameters] parameters + # @param [HandlerContext] context # @return [String] - def resolve(parameters) + def resolve(context) + parameters = AuthParameters.create(context) options = [] options << 'smithy.api#noAuth' options diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 9c0d5e19e..c8139d906 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -4,6 +4,7 @@ require_relative 'plugins/auth' require_relative 'plugins/endpoint' +require 'smithy-client/plugins/auth' require 'smithy-client/plugins/checksum_required' require 'smithy-client/plugins/content_length' require 'smithy-client/plugins/default_params' @@ -33,6 +34,7 @@ class Client < Smithy::Client::Base add_plugin(::Weather::Plugins::Auth) add_plugin(::Weather::Plugins::Endpoint) + add_plugin(Smithy::Client::Plugins::Auth) add_plugin(Smithy::Client::Plugins::ChecksumRequired) add_plugin(Smithy::Client::Plugins::ContentLength) add_plugin(Smithy::Client::Plugins::DefaultParams) @@ -351,6 +353,14 @@ def protocols {} end + + # @api private + def identity_providers(context) + { + Smithy::Client::Identities::Anonymous => context.config.anonymous_provider, + } + end + # @api private def errors_module Errors diff --git a/projections/weather/lib/weather/plugins/auth.rb b/projections/weather/lib/weather/plugins/auth.rb index 1bdcfcb41..a938769b9 100644 --- a/projections/weather/lib/weather/plugins/auth.rb +++ b/projections/weather/lib/weather/plugins/auth.rb @@ -27,78 +27,6 @@ class Auth < Smithy::Client::Plugin 'smithy.api#noAuth' => config.anonymous_auth_scheme, } end - - # @api private - class Handler < Smithy::Client::Handler - def call(context) - # TODO: apply endpoint auth properties if present - auth_params = AuthParameters.create(context) - auth_options = context.config.auth_resolver.resolve(auth_params) - context[:auth] = resolve_auth(context, auth_options) - @handler.call(context) - end - - private - - def resolve_auth(context, auth_options) - failures = [] - - raise 'No auth options were resolved' if auth_options.empty? - - identity_providers = { - Smithy::Client::Identities::Anonymous => context.config.anonymous_provider, - } - - auth_options.each do |auth_option| - auth_scheme = context.config.auth_schemes[auth_option] - resolved_auth = try_load_auth_scheme( - auth_option, - auth_scheme, - identity_providers, - failures - ) - - return resolved_auth if resolved_auth - end - - raise failures.join("\n") - end - - def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) - scheme_id = auth_option - unless auth_scheme - failures << "Auth scheme #{scheme_id} was not enabled " \ - 'for this request' - return - end - - identity_provider = auth_scheme.identity_provider(identity_providers) - unless identity_provider - failures << "Auth scheme #{scheme_id} did not have an " \ - 'identity resolver configured' - return - end - - identity = identity_provider.identity - - ResolvedAuth.new( - identity: identity, - signer: auth_scheme.signer - ) - end - - # @api private - class ResolvedAuth - def initialize(options = {}) - @identity = options[:identity] - @signer = options[:signer] - end - - attr_accessor :identity, :signer - end - end - - handler(Handler, step: :sign, priority: 70) end end end diff --git a/projections/weather/sig/weather/auth_resolver.rbs b/projections/weather/sig/weather/auth_resolver.rbs index a41a4619c..827c02b80 100644 --- a/projections/weather/sig/weather/auth_resolver.rbs +++ b/projections/weather/sig/weather/auth_resolver.rbs @@ -1,5 +1,5 @@ module Weather class AuthResolver - def resolve: (AuthParameters) -> Array[String] + def resolve: (?Hash[Symbol, untyped]) -> Array[String] end end From 6918c9e025be7a87e827a98abf2db6436ee1567f Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 24 Jun 2025 09:02:47 -0700 Subject: [PATCH 17/19] Rubocop --- gems/smithy-cbor/lib/smithy-cbor/decoder.rb | 2 +- gems/smithy-client/lib/smithy-client/plugins/auth.rb | 6 +++--- .../smithy-client/lib/smithy-client/signers/http_api_key.rb | 4 +--- gems/smithy-client/lib/smithy-client/util.rb | 2 +- gems/smithy/lib/smithy/welds/plugins.rb | 2 +- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/gems/smithy-cbor/lib/smithy-cbor/decoder.rb b/gems/smithy-cbor/lib/smithy-cbor/decoder.rb index 167b86bff..87b5df269 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/decoder.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/decoder.rb @@ -171,7 +171,7 @@ def read_bignum(tag_value) end end - def read_boolean + def read_boolean # rubocop:disable Naming/PredicateMethod _major_type, add_info = read_info case add_info when 20 then false diff --git a/gems/smithy-client/lib/smithy-client/plugins/auth.rb b/gems/smithy-client/lib/smithy-client/plugins/auth.rb index af20ae57a..abb91bdb5 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/auth.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/auth.rb @@ -42,14 +42,14 @@ def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) scheme_id = auth_option unless auth_scheme failures << "Auth scheme #{scheme_id} was not enabled " \ - 'for this request' + 'for this request' return end identity_provider = auth_scheme.identity_provider(identity_providers) unless identity_provider failures << "Auth scheme #{scheme_id} did not have an " \ - 'identity resolver configured' + 'identity resolver configured' return end @@ -65,4 +65,4 @@ def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) end end end -end \ No newline at end of file +end diff --git a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb index a657d4d64..056b9ae8d 100644 --- a/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb +++ b/gems/smithy-client/lib/smithy-client/signers/http_api_key.rb @@ -5,8 +5,7 @@ module Client module Signers # A signer that signs requests using the HTTP API Key Auth scheme. class HttpApiKey < Signer - # rubocop:disable Metrics/AbcSize - def sign(context) + def sign(context) # rubocop:disable Metrics/AbcSize reset(context) request = context.http_request identity = context.auth[:identity] @@ -20,7 +19,6 @@ def sign(context) append_query_param(request, name, identity.key) end end - # rubocop:enable Metrics/AbcSize def reset(context) request = context.http_request diff --git a/gems/smithy-client/lib/smithy-client/util.rb b/gems/smithy-client/lib/smithy-client/util.rb index b8968b148..6f3c4f6c3 100644 --- a/gems/smithy-client/lib/smithy-client/util.rb +++ b/gems/smithy-client/lib/smithy-client/util.rb @@ -4,7 +4,7 @@ module Smithy module Client # @api private module Util - def self.str_to_bool(str) + def self.str_to_bool(str) # rubocop:disable Naming/PredicateMethod case str when 'true' then true when 'false' then false diff --git a/gems/smithy/lib/smithy/welds/plugins.rb b/gems/smithy/lib/smithy/welds/plugins.rb index 4726b5038..e2a86ceea 100644 --- a/gems/smithy/lib/smithy/welds/plugins.rb +++ b/gems/smithy/lib/smithy/welds/plugins.rb @@ -28,7 +28,7 @@ def for?(_service) true end - def add_plugins + def add_plugins # rubocop:disable Metrics/MethodLength base_path = 'smithy-client/plugins' { Smithy::Client::Plugins::Auth => { require_path: "#{base_path}/auth" }, From 1f4f47947bd503473bbeae9066e7e6c44b8cc29e Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 24 Jun 2025 09:08:28 -0700 Subject: [PATCH 18/19] Update projections --- projections/shapes/sig/shapes/auth_resolver.rbs | 2 +- projections/weather/sig/weather/auth_resolver.rbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projections/shapes/sig/shapes/auth_resolver.rbs b/projections/shapes/sig/shapes/auth_resolver.rbs index c7141157b..18d7c38bb 100644 --- a/projections/shapes/sig/shapes/auth_resolver.rbs +++ b/projections/shapes/sig/shapes/auth_resolver.rbs @@ -1,5 +1,5 @@ module ShapeService class AuthResolver - def resolve: (?Hash[Symbol, untyped]) -> Array[String] + def resolve: (Smithy::Client::HandlerContext) -> Array[String] end end diff --git a/projections/weather/sig/weather/auth_resolver.rbs b/projections/weather/sig/weather/auth_resolver.rbs index 827c02b80..349008743 100644 --- a/projections/weather/sig/weather/auth_resolver.rbs +++ b/projections/weather/sig/weather/auth_resolver.rbs @@ -1,5 +1,5 @@ module Weather class AuthResolver - def resolve: (?Hash[Symbol, untyped]) -> Array[String] + def resolve: (Smithy::Client::HandlerContext) -> Array[String] end end From d031b345c7f268ef9cc4a2ff42a61f5b1d11b7a5 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 25 Jun 2025 13:00:54 -0700 Subject: [PATCH 19/19] Refactor auth handler --- .../lib/smithy-client/auth_schemes/auth.rb | 63 +++++++++++++++++ .../lib/smithy-client/plugins/auth.rb | 68 ------------------- .../plugins/checksum_required_spec.rb | 1 - .../plugins/http_api_key_auth_spec.rb | 1 - .../plugins/http_basic_auth_spec.rb | 1 - .../plugins/http_bearer_auth_spec.rb | 1 - .../smithy/templates/client/auth_plugin.erb | 4 ++ gems/smithy/lib/smithy/welds/plugins.rb | 4 +- projections/shapes/lib/shapes/client.rb | 2 - projections/shapes/lib/shapes/plugins/auth.rb | 4 ++ projections/weather/lib/weather/client.rb | 2 - .../weather/lib/weather/plugins/auth.rb | 4 ++ 12 files changed, 76 insertions(+), 79 deletions(-) create mode 100644 gems/smithy-client/lib/smithy-client/auth_schemes/auth.rb delete mode 100644 gems/smithy-client/lib/smithy-client/plugins/auth.rb diff --git a/gems/smithy-client/lib/smithy-client/auth_schemes/auth.rb b/gems/smithy-client/lib/smithy-client/auth_schemes/auth.rb new file mode 100644 index 000000000..4ed3b5a97 --- /dev/null +++ b/gems/smithy-client/lib/smithy-client/auth_schemes/auth.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module Smithy + module Client + module AuthSchemes + # @api private + class Handler < Smithy::Client::Handler + def call(context) + # TODO: apply endpoint auth properties if present + auth_options = context.config.auth_resolver.resolve(context) + context.auth = resolve_auth(context, auth_options) + @handler.call(context) + end + + private + + def resolve_auth(context, auth_options) + failures = [] + + raise 'No auth options were resolved' if auth_options.empty? + + identity_providers = context.client.class.identity_providers(context) + + auth_options.each do |auth_option| + auth_scheme = context.config.auth_schemes[auth_option] + resolved_auth = try_load_auth_scheme( + auth_option, + auth_scheme, + identity_providers, + failures + ) + + return resolved_auth if resolved_auth + end + + raise failures.join("\n") + end + + def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) + scheme_id = auth_option + unless auth_scheme + failures << "Auth scheme #{scheme_id} was not enabled " \ + 'for this request' + return + end + + identity_provider = auth_scheme.identity_provider(identity_providers) + unless identity_provider + failures << "Auth scheme #{scheme_id} did not have an " \ + 'identity resolver configured' + return + end + + { + scheme_id: scheme_id, + identity: identity_provider.identity, + signer: auth_scheme.signer + } + end + end + end + end +end diff --git a/gems/smithy-client/lib/smithy-client/plugins/auth.rb b/gems/smithy-client/lib/smithy-client/plugins/auth.rb deleted file mode 100644 index abb91bdb5..000000000 --- a/gems/smithy-client/lib/smithy-client/plugins/auth.rb +++ /dev/null @@ -1,68 +0,0 @@ -# frozen_string_literal: true - -module Smithy - module Client - module Plugins - # @api private - class Auth < Plugin - # @api private - class Handler < Smithy::Client::Handler - def call(context) - # TODO: apply endpoint auth properties if present - auth_options = context.config.auth_resolver.resolve(context) - context.auth = resolve_auth(context, auth_options) - @handler.call(context) - end - - private - - def resolve_auth(context, auth_options) - failures = [] - - raise 'No auth options were resolved' if auth_options.empty? - - identity_providers = context.client.class.identity_providers(context) - - auth_options.each do |auth_option| - auth_scheme = context.config.auth_schemes[auth_option] - resolved_auth = try_load_auth_scheme( - auth_option, - auth_scheme, - identity_providers, - failures - ) - - return resolved_auth if resolved_auth - end - - raise failures.join("\n") - end - - def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) - scheme_id = auth_option - unless auth_scheme - failures << "Auth scheme #{scheme_id} was not enabled " \ - 'for this request' - return - end - - identity_provider = auth_scheme.identity_provider(identity_providers) - unless identity_provider - failures << "Auth scheme #{scheme_id} did not have an " \ - 'identity resolver configured' - return - end - - { - scheme_id: scheme_id, - identity: identity_provider.identity, - signer: auth_scheme.signer - } - end - end - - handler(Handler, step: :sign, priority: 70) - end - end - end -end diff --git a/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb index 08a43adc2..ac27c83b3 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/checksum_required_spec.rb @@ -17,7 +17,6 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) - client_class.add_plugin(Auth) client_class.add_plugin(ChecksumRequired) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb index e10933bfb..4380b391c 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_api_key_auth_spec.rb @@ -17,7 +17,6 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) - client_class.add_plugin(Auth) client_class.add_plugin(HttpApiKeyAuth) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb index fbd8486c5..a502160e8 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_basic_auth_spec.rb @@ -17,7 +17,6 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) - client_class.add_plugin(Auth) client_class.add_plugin(HttpBasicAuth) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) diff --git a/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb index cbd99ac6f..aa5af8816 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/http_bearer_auth_spec.rb @@ -17,7 +17,6 @@ module Plugins client_class.add_plugin(sample_client::Plugins::Auth) client_class.add_plugin(sample_client::Plugins::Endpoint) client_class.add_plugin(AnonymousAuth) - client_class.add_plugin(Auth) client_class.add_plugin(HttpBearerAuth) client_class.add_plugin(Protocol) client_class.add_plugin(SignRequests) diff --git a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb index f0813f34d..ff1354193 100644 --- a/gems/smithy/lib/smithy/templates/client/auth_plugin.erb +++ b/gems/smithy/lib/smithy/templates/client/auth_plugin.erb @@ -2,6 +2,8 @@ # This is generated code! +require 'smithy-client/auth_schemes/auth' + module <%= module_name %> module Plugins # @api private @@ -29,6 +31,8 @@ module <%= module_name %> <% end -%> } end + + handler(Smithy::Client::AuthSchemes::Handler, step: :sign, priority: 70) end end end diff --git a/gems/smithy/lib/smithy/welds/plugins.rb b/gems/smithy/lib/smithy/welds/plugins.rb index e2a86ceea..c84ce6380 100644 --- a/gems/smithy/lib/smithy/welds/plugins.rb +++ b/gems/smithy/lib/smithy/welds/plugins.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'smithy-client/plugins/auth' require 'smithy-client/plugins/checksum_required' require 'smithy-client/plugins/content_length' require 'smithy-client/plugins/default_params' @@ -28,10 +27,9 @@ def for?(_service) true end - def add_plugins # rubocop:disable Metrics/MethodLength + def add_plugins base_path = 'smithy-client/plugins' { - Smithy::Client::Plugins::Auth => { require_path: "#{base_path}/auth" }, Smithy::Client::Plugins::ChecksumRequired => { require_path: "#{base_path}/checksum_required" }, Smithy::Client::Plugins::ContentLength => { require_path: "#{base_path}/content_length" }, Smithy::Client::Plugins::DefaultParams => { require_path: "#{base_path}/default_params" }, diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 055e658c0..0c320ab24 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -4,7 +4,6 @@ require_relative 'plugins/auth' require_relative 'plugins/endpoint' -require 'smithy-client/plugins/auth' require 'smithy-client/plugins/checksum_required' require 'smithy-client/plugins/content_length' require 'smithy-client/plugins/default_params' @@ -34,7 +33,6 @@ class Client < Smithy::Client::Base add_plugin(::ShapeService::Plugins::Auth) add_plugin(::ShapeService::Plugins::Endpoint) - add_plugin(Smithy::Client::Plugins::Auth) add_plugin(Smithy::Client::Plugins::ChecksumRequired) add_plugin(Smithy::Client::Plugins::ContentLength) add_plugin(Smithy::Client::Plugins::DefaultParams) diff --git a/projections/shapes/lib/shapes/plugins/auth.rb b/projections/shapes/lib/shapes/plugins/auth.rb index bd3827efc..72f262019 100644 --- a/projections/shapes/lib/shapes/plugins/auth.rb +++ b/projections/shapes/lib/shapes/plugins/auth.rb @@ -2,6 +2,8 @@ # This is generated code! +require 'smithy-client/auth_schemes/auth' + module ShapeService module Plugins # @api private @@ -27,6 +29,8 @@ class Auth < Smithy::Client::Plugin 'smithy.api#noAuth' => config.anonymous_auth_scheme, } end + + handler(Smithy::Client::AuthSchemes::Handler, step: :sign, priority: 70) end end end diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index c8139d906..392a5faff 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -4,7 +4,6 @@ require_relative 'plugins/auth' require_relative 'plugins/endpoint' -require 'smithy-client/plugins/auth' require 'smithy-client/plugins/checksum_required' require 'smithy-client/plugins/content_length' require 'smithy-client/plugins/default_params' @@ -34,7 +33,6 @@ class Client < Smithy::Client::Base add_plugin(::Weather::Plugins::Auth) add_plugin(::Weather::Plugins::Endpoint) - add_plugin(Smithy::Client::Plugins::Auth) add_plugin(Smithy::Client::Plugins::ChecksumRequired) add_plugin(Smithy::Client::Plugins::ContentLength) add_plugin(Smithy::Client::Plugins::DefaultParams) diff --git a/projections/weather/lib/weather/plugins/auth.rb b/projections/weather/lib/weather/plugins/auth.rb index a938769b9..1d73285d8 100644 --- a/projections/weather/lib/weather/plugins/auth.rb +++ b/projections/weather/lib/weather/plugins/auth.rb @@ -2,6 +2,8 @@ # This is generated code! +require 'smithy-client/auth_schemes/auth' + module Weather module Plugins # @api private @@ -27,6 +29,8 @@ class Auth < Smithy::Client::Plugin 'smithy.api#noAuth' => config.anonymous_auth_scheme, } end + + handler(Smithy::Client::AuthSchemes::Handler, step: :sign, priority: 70) end end end