From 5ffec5c6279e5175c61db8655a18dd4e57058b67 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 15 Feb 2023 23:29:19 +0800 Subject: [PATCH 01/14] initial work on security schema (only jwt bearer) --- lib/openapi_parser/schemas.rb | 2 ++ lib/openapi_parser/schemas/classes.rb | 2 ++ lib/openapi_parser/schemas/components.rb | 4 ++++ lib/openapi_parser/schemas/jwt.rb | 13 +++++++++++++ lib/openapi_parser/schemas/security_schemes.rb | 8 ++++++++ 5 files changed, 29 insertions(+) create mode 100644 lib/openapi_parser/schemas/jwt.rb create mode 100644 lib/openapi_parser/schemas/security_schemes.rb diff --git a/lib/openapi_parser/schemas.rb b/lib/openapi_parser/schemas.rb index 97a184a..e8664c9 100644 --- a/lib/openapi_parser/schemas.rb +++ b/lib/openapi_parser/schemas.rb @@ -15,3 +15,5 @@ require_relative 'schemas/media_type' require_relative 'schemas/schema' require_relative 'schemas/header' +require_relative 'schemas/security_schemes' +require_relative 'schemas/jwt' diff --git a/lib/openapi_parser/schemas/classes.rb b/lib/openapi_parser/schemas/classes.rb index eb385d9..95373c0 100644 --- a/lib/openapi_parser/schemas/classes.rb +++ b/lib/openapi_parser/schemas/classes.rb @@ -16,4 +16,6 @@ class MediaType < Base; end class Schema < Base; end class Components < Base; end class Header < Base; end + class SecurityScheme < Base; end + class Jwt < Base; end end diff --git a/lib/openapi_parser/schemas/components.rb b/lib/openapi_parser/schemas/components.rb index 77f890d..c036aaf 100644 --- a/lib/openapi_parser/schemas/components.rb +++ b/lib/openapi_parser/schemas/components.rb @@ -24,5 +24,9 @@ class Components < Base # @!attribute [r] headers # @return [Hash{String => Header}, nil] header objects openapi_attr_hash_object :headers, Header, reference: true + + # @!attribute [r] securitySchemes + # @return [Hash{String => SecurityScheme}, nil] + openapi_attr_hash_object :security_schemes, SecurityScheme, reference: false, schema_key: :securitySchemes end end diff --git a/lib/openapi_parser/schemas/jwt.rb b/lib/openapi_parser/schemas/jwt.rb new file mode 100644 index 0000000..afe39f8 --- /dev/null +++ b/lib/openapi_parser/schemas/jwt.rb @@ -0,0 +1,13 @@ +module OpenAPIParser::Schemas + class Jwt < Base + # @!attribute [r] type + # @return [String, nil] + # @!attribute [r] scheme + # @return [String, nil] + # @!attribute [r] bearerFormat + # @return [String, nil] + + openapi_attr_values :type, :scheme, + :bearerFormat + end +end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb new file mode 100644 index 0000000..6870220 --- /dev/null +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -0,0 +1,8 @@ +module OpenAPIParser::Schemas + class SecurityScheme < Base + # @!attribute [r] jwt + # @return [Jwt, nil] + openapi_attr_object :jwt, Jwt, reference: false + + end +end From ef238a1fb1cb8c2572a7d22fe3de9e14a96b5212 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Thu, 16 Feb 2023 19:32:50 +0800 Subject: [PATCH 02/14] add more code for jwt token --- lib/openapi_parser/schemas/components.rb | 4 ++++ lib/openapi_parser/schemas/security_schemes.rb | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/openapi_parser/schemas/components.rb b/lib/openapi_parser/schemas/components.rb index c036aaf..0eef50c 100644 --- a/lib/openapi_parser/schemas/components.rb +++ b/lib/openapi_parser/schemas/components.rb @@ -28,5 +28,9 @@ class Components < Base # @!attribute [r] securitySchemes # @return [Hash{String => SecurityScheme}, nil] openapi_attr_hash_object :security_schemes, SecurityScheme, reference: false, schema_key: :securitySchemes + + def validate_security_schemes(params, options) + security_schemes&.validate(params, options) + end end end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb index 6870220..556aa0f 100644 --- a/lib/openapi_parser/schemas/security_schemes.rb +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -4,5 +4,10 @@ class SecurityScheme < Base # @return [Jwt, nil] openapi_attr_object :jwt, Jwt, reference: false + # validate by jwt + # @param [Object] value + def validate(value) + OpenAPIParser::SchemaValidator.validate(value, jwt, OpenAPIParser::SchemaValidator::Options.new) + end end end From 57c9be1236295cbdfb34da95655fbf2a62348382 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Mon, 20 Feb 2023 15:32:25 +0800 Subject: [PATCH 03/14] add security --- lib/openapi_parser/request_operation.rb | 1 + lib/openapi_parser/schemas/operation.rb | 11 +++++++++-- lib/openapi_parser/schemas/security_schemes.rb | 8 +------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/openapi_parser/request_operation.rb b/lib/openapi_parser/request_operation.rb index d0312b9..ce40645 100644 --- a/lib/openapi_parser/request_operation.rb +++ b/lib/openapi_parser/request_operation.rb @@ -50,6 +50,7 @@ def validate_path_params(options = nil) def validate_request_body(content_type, params, options = nil) options ||= config.request_body_options operation_object&.validate_request_body(content_type, params, options) + operation_object.validate_security(params, options) end # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index 96b729c..03812a7 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -7,10 +7,10 @@ module OpenAPIParser::Schemas class Operation < Base include OpenAPIParser::ParameterValidatable - openapi_attr_values :tags, :summary, :description, :deprecated + openapi_attr_values :tags, :summary, :description, :deprecated, :security openapi_attr_value :operation_id, schema_key: :operationId - + openapi_attr_list_object :parameters, Parameter, reference: true # @!attribute [r] request_body @@ -30,5 +30,12 @@ def validate_request_body(content_type, params, options) def validate_response(response_body, response_validate_options) responses&.validate(response_body, response_validate_options) end + + def validate_security(params, options) + # test - will show the list of security options + security.each do |sec| + puts sec + end + end end end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb index 556aa0f..ecc2ac9 100644 --- a/lib/openapi_parser/schemas/security_schemes.rb +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -1,13 +1,7 @@ module OpenAPIParser::Schemas class SecurityScheme < Base - # @!attribute [r] jwt - # @return [Jwt, nil] - openapi_attr_object :jwt, Jwt, reference: false - # validate by jwt - # @param [Object] value - def validate(value) - OpenAPIParser::SchemaValidator.validate(value, jwt, OpenAPIParser::SchemaValidator::Options.new) + def validate(params, options) end end end From eb9c334aa3ea1e989b4cc11e04e2b94302ad855c Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Mon, 20 Feb 2023 17:09:00 +0800 Subject: [PATCH 04/14] remove unnecessary code --- lib/openapi_parser/request_operation.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/openapi_parser/request_operation.rb b/lib/openapi_parser/request_operation.rb index ce40645..d0312b9 100644 --- a/lib/openapi_parser/request_operation.rb +++ b/lib/openapi_parser/request_operation.rb @@ -50,7 +50,6 @@ def validate_path_params(options = nil) def validate_request_body(content_type, params, options = nil) options ||= config.request_body_options operation_object&.validate_request_body(content_type, params, options) - operation_object.validate_security(params, options) end # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body From 93e073248d2dbbfbc7d84d41794981c01012e69b Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 22 Feb 2023 02:36:54 +0800 Subject: [PATCH 05/14] Almost there... --- lib/openapi_parser/path_item_finder.rb | 2 ++ lib/openapi_parser/request_operation.rb | 14 ++++++++++---- lib/openapi_parser/schemas.rb | 1 + lib/openapi_parser/schemas/classes.rb | 1 + lib/openapi_parser/schemas/components.rb | 4 ++++ lib/openapi_parser/schemas/openapi.rb | 2 +- lib/openapi_parser/schemas/operation.rb | 7 ++++++- lib/openapi_parser/schemas/security_schemes.rb | 13 +++++++++++++ spec/data/petstore-expanded.yaml | 5 +++++ spec/openapi_parser/schemas/components_spec.rb | 2 ++ 10 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 lib/openapi_parser/schemas/security_schemes.rb diff --git a/lib/openapi_parser/path_item_finder.rb b/lib/openapi_parser/path_item_finder.rb index 8113b3e..8405a9b 100644 --- a/lib/openapi_parser/path_item_finder.rb +++ b/lib/openapi_parser/path_item_finder.rb @@ -9,6 +9,8 @@ def initialize(paths) # @param [String] request_path # @return [Result, nil] def operation_object(http_method, request_path) + puts "@paths: #{@paths.inspect}" + puts "@paths.path #{@paths.path}" if (path_item_object = @paths.path[request_path]) if (op = path_item_object.operation(http_method)) return Result.new(path_item_object, op, request_path, {}) # find no path_params path diff --git a/lib/openapi_parser/request_operation.rb b/lib/openapi_parser/request_operation.rb index d0312b9..758a8f3 100644 --- a/lib/openapi_parser/request_operation.rb +++ b/lib/openapi_parser/request_operation.rb @@ -5,11 +5,11 @@ class << self # @param [OpenAPIParser::Config] config # @param [OpenAPIParser::PathItemFinder] path_item_finder # @return [OpenAPIParser::RequestOperation, nil] - def create(http_method, request_path, path_item_finder, config) + def create(http_method, request_path, path_item_finder, config, components) result = path_item_finder.operation_object(http_method, request_path) return nil unless result - self.new(http_method, result, config) + self.new(http_method, result, config, components.security_schemes) end end @@ -25,18 +25,23 @@ def create(http_method, request_path, path_item_finder, config) # @return [String] # @!attribute [r] path_item # @return [OpenAPIParser::Schemas::PathItem] - attr_reader :operation_object, :path_params, :config, :http_method, :original_path, :path_item + attr_reader :operation_object, :path_params, :config, :http_method, :original_path, :path_item, :security_schemes # @param [String] http_method # @param [OpenAPIParser::PathItemFinder::Result] result # @param [OpenAPIParser::Config] config - def initialize(http_method, result, config) + def initialize(http_method, result, config, security_schemes) @http_method = http_method.to_s @original_path = result.original_path @operation_object = result.operation_object @path_params = result.path_params || {} @path_item = result.path_item_object @config = config + @security_schemes = security_schemes + end + + def validate_security(security_schemes) + operation_object.validate_security_schemes(security_schemes) end def validate_path_params(options = nil) @@ -50,6 +55,7 @@ def validate_path_params(options = nil) def validate_request_body(content_type, params, options = nil) options ||= config.request_body_options operation_object&.validate_request_body(content_type, params, options) + validate_security(security_schemes) end # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body diff --git a/lib/openapi_parser/schemas.rb b/lib/openapi_parser/schemas.rb index 97a184a..838414e 100644 --- a/lib/openapi_parser/schemas.rb +++ b/lib/openapi_parser/schemas.rb @@ -15,3 +15,4 @@ require_relative 'schemas/media_type' require_relative 'schemas/schema' require_relative 'schemas/header' +require_relative 'schemas/security_schemes' diff --git a/lib/openapi_parser/schemas/classes.rb b/lib/openapi_parser/schemas/classes.rb index eb385d9..5350ffb 100644 --- a/lib/openapi_parser/schemas/classes.rb +++ b/lib/openapi_parser/schemas/classes.rb @@ -16,4 +16,5 @@ class MediaType < Base; end class Schema < Base; end class Components < Base; end class Header < Base; end + class SecuritySchemes < Base; end end diff --git a/lib/openapi_parser/schemas/components.rb b/lib/openapi_parser/schemas/components.rb index 77f890d..1d0a30f 100644 --- a/lib/openapi_parser/schemas/components.rb +++ b/lib/openapi_parser/schemas/components.rb @@ -24,5 +24,9 @@ class Components < Base # @!attribute [r] headers # @return [Hash{String => Header}, nil] header objects openapi_attr_hash_object :headers, Header, reference: true + + # @!attribute [r] security_schemes + # @return [Hash{String => Header}, nil] + openapi_attr_hash_object :security_schemes, SecuritySchemes, reference: true, schema_key: :securitySchemes end end diff --git a/lib/openapi_parser/schemas/openapi.rb b/lib/openapi_parser/schemas/openapi.rb index b55a557..925ebdc 100644 --- a/lib/openapi_parser/schemas/openapi.rb +++ b/lib/openapi_parser/schemas/openapi.rb @@ -31,7 +31,7 @@ def initialize(raw_schema, config, uri: nil, schema_registry: {}) # @return [OpenAPIParser::RequestOperation, nil] def request_operation(http_method, request_path) - OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder, @config) + OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder, @config, components) end # load another schema with shared config and schema_registry diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index 96b729c..bf4b11b 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -7,7 +7,7 @@ module OpenAPIParser::Schemas class Operation < Base include OpenAPIParser::ParameterValidatable - openapi_attr_values :tags, :summary, :description, :deprecated + openapi_attr_values :tags, :summary, :description, :deprecated, :security openapi_attr_value :operation_id, schema_key: :operationId @@ -30,5 +30,10 @@ def validate_request_body(content_type, params, options) def validate_response(response_body, response_validate_options) responses&.validate(response_body, response_validate_options) end + + #def validate_security_schemes(security_schemes) + # puts "SECURITY SCHEME: #{security_schemes}" + # # test - will show the list of security options + #end end end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb new file mode 100644 index 0000000..44fb93b --- /dev/null +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -0,0 +1,13 @@ +module OpenAPIParser::Schemas + class SecuritySchemes < Base + + openapi_attr_values :type, :description, :schema + openapi_attr_value :bearer_format, schema_key: :bearerFormat + + def validate_security_schemes(params, options) + if self.type == "http" && self.schema == "bearer" && self.bearer_format == "JWT" + puts "YAY!" + end + end + end +end diff --git a/spec/data/petstore-expanded.yaml b/spec/data/petstore-expanded.yaml index eb17b83..3979b06 100644 --- a/spec/data/petstore-expanded.yaml +++ b/spec/data/petstore-expanded.yaml @@ -306,6 +306,11 @@ paths: $ref: '#/components/schemas/Pet' components: + securitySchemes: + jwt: + type: "http" + scheme: "bearer" + bearerFormat: "JWT" parameters: test: name: limit diff --git a/spec/openapi_parser/schemas/components_spec.rb b/spec/openapi_parser/schemas/components_spec.rb index bb8c16c..f8abb29 100644 --- a/spec/openapi_parser/schemas/components_spec.rb +++ b/spec/openapi_parser/schemas/components_spec.rb @@ -21,6 +21,8 @@ expect(subject.request_bodies['test_body'].class).to eq OpenAPIParser::Schemas::RequestBody expect(subject.request_bodies['test_body'].object_reference).to eq '#/components/requestBodies/test_body' + expect(subject.security_schemes['jwt'].class).to eq OpenAPIParser::Schemas::SecuritySchemes + expect(subject.headers['X-Rate-Limit-Limit'].class).to eq OpenAPIParser::Schemas::Header end end From 6b7b75aa612d6d408f86fa6fd1ffe06f1c843e3e Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 22 Feb 2023 02:43:10 +0800 Subject: [PATCH 06/14] remove old file --- lib/openapi_parser/schemas/jwt.rb | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 lib/openapi_parser/schemas/jwt.rb diff --git a/lib/openapi_parser/schemas/jwt.rb b/lib/openapi_parser/schemas/jwt.rb deleted file mode 100644 index afe39f8..0000000 --- a/lib/openapi_parser/schemas/jwt.rb +++ /dev/null @@ -1,13 +0,0 @@ -module OpenAPIParser::Schemas - class Jwt < Base - # @!attribute [r] type - # @return [String, nil] - # @!attribute [r] scheme - # @return [String, nil] - # @!attribute [r] bearerFormat - # @return [String, nil] - - openapi_attr_values :type, :scheme, - :bearerFormat - end -end From 2cb7f3051ef841eb0b3432dce03a922459b5f7ed Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 22 Feb 2023 04:41:43 +0800 Subject: [PATCH 07/14] add more improvements --- lib/openapi_parser/path_item_finder.rb | 2 -- lib/openapi_parser/request_operation.rb | 7 ++++--- lib/openapi_parser/schemas/components.rb | 6 +----- lib/openapi_parser/schemas/openapi.rb | 2 +- lib/openapi_parser/schemas/operation.rb | 7 +++---- lib/openapi_parser/schemas/security_schemes.rb | 10 ++++++---- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/lib/openapi_parser/path_item_finder.rb b/lib/openapi_parser/path_item_finder.rb index 8405a9b..8113b3e 100644 --- a/lib/openapi_parser/path_item_finder.rb +++ b/lib/openapi_parser/path_item_finder.rb @@ -9,8 +9,6 @@ def initialize(paths) # @param [String] request_path # @return [Result, nil] def operation_object(http_method, request_path) - puts "@paths: #{@paths.inspect}" - puts "@paths.path #{@paths.path}" if (path_item_object = @paths.path[request_path]) if (op = path_item_object.operation(http_method)) return Result.new(path_item_object, op, request_path, {}) # find no path_params path diff --git a/lib/openapi_parser/request_operation.rb b/lib/openapi_parser/request_operation.rb index 758a8f3..0004fbc 100644 --- a/lib/openapi_parser/request_operation.rb +++ b/lib/openapi_parser/request_operation.rb @@ -5,11 +5,11 @@ class << self # @param [OpenAPIParser::Config] config # @param [OpenAPIParser::PathItemFinder] path_item_finder # @return [OpenAPIParser::RequestOperation, nil] - def create(http_method, request_path, path_item_finder, config, components) + def create(http_method, request_path, path_item_finder, config, security_schemes) result = path_item_finder.operation_object(http_method, request_path) return nil unless result - self.new(http_method, result, config, components.security_schemes) + self.new(http_method, result, config, security_schemes) end end @@ -54,8 +54,9 @@ def validate_path_params(options = nil) # @param [OpenAPIParser::SchemaValidator::Options] options def validate_request_body(content_type, params, options = nil) options ||= config.request_body_options - operation_object&.validate_request_body(content_type, params, options) + validate_security(security_schemes) + operation_object&.validate_request_body(content_type, params, options) end # @param [OpenAPIParser::RequestOperation::ValidatableResponseBody] response_body diff --git a/lib/openapi_parser/schemas/components.rb b/lib/openapi_parser/schemas/components.rb index 3ce7155..56f6850 100644 --- a/lib/openapi_parser/schemas/components.rb +++ b/lib/openapi_parser/schemas/components.rb @@ -27,10 +27,6 @@ class Components < Base # @!attribute [r] security_schemes # @return [Hash{String => Header}, nil] - openapi_attr_hash_object :security_schemes, SecuritySchemes, reference: true, schema_key: :securitySchemes - - #def validate_sec - # security_schemes.validate_security_schemes - #end + openapi_attr_object :security_schemes, SecuritySchemes, reference: true, schema_key: :securitySchemes end end diff --git a/lib/openapi_parser/schemas/openapi.rb b/lib/openapi_parser/schemas/openapi.rb index 925ebdc..2baabf9 100644 --- a/lib/openapi_parser/schemas/openapi.rb +++ b/lib/openapi_parser/schemas/openapi.rb @@ -31,7 +31,7 @@ def initialize(raw_schema, config, uri: nil, schema_registry: {}) # @return [OpenAPIParser::RequestOperation, nil] def request_operation(http_method, request_path) - OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder, @config, components) + OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder, @config, components&.security_schemes) end # load another schema with shared config and schema_registry diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index 47b9d2d..b9e6635 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -31,9 +31,8 @@ def validate_response(response_body, response_validate_options) responses&.validate(response_body, response_validate_options) end - #def validate_security_schemes(security_schemes) - # puts "SECURITY SCHEME: #{security_schemes}" - # # test - will show the list of security options - #end + def validate_security_schemes(securitySchemes) + securitySchemes.validate_security_schemes(security) + end end end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb index 44fb93b..c998736 100644 --- a/lib/openapi_parser/schemas/security_schemes.rb +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -1,12 +1,14 @@ module OpenAPIParser::Schemas class SecuritySchemes < Base - openapi_attr_values :type, :description, :schema + openapi_attr_values :type, :description, :scheme openapi_attr_value :bearer_format, schema_key: :bearerFormat - def validate_security_schemes(params, options) - if self.type == "http" && self.schema == "bearer" && self.bearer_format == "JWT" - puts "YAY!" + def validate_security_schemes(security) + puts "Validation code is executing!" + if self.type == "http" && self.scheme == "bearer" && self.bearer_format == "JWT" + # check if the JWT token is being sent and try to decode. + # if JWT token does not exist or token cannot decode, then deny access end end end From fa56cee23c9423f2949bd09df925446025520f83 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 22 Feb 2023 07:31:35 +0800 Subject: [PATCH 08/14] update working code --- lib/openapi_parser/schemas/components.rb | 2 +- lib/openapi_parser/schemas/operation.rb | 5 ++++- lib/openapi_parser/schemas/security_schemes.rb | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/openapi_parser/schemas/components.rb b/lib/openapi_parser/schemas/components.rb index 56f6850..1d0a30f 100644 --- a/lib/openapi_parser/schemas/components.rb +++ b/lib/openapi_parser/schemas/components.rb @@ -27,6 +27,6 @@ class Components < Base # @!attribute [r] security_schemes # @return [Hash{String => Header}, nil] - openapi_attr_object :security_schemes, SecuritySchemes, reference: true, schema_key: :securitySchemes + openapi_attr_hash_object :security_schemes, SecuritySchemes, reference: true, schema_key: :securitySchemes end end diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index b9e6635..19e4b1c 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -32,7 +32,10 @@ def validate_response(response_body, response_validate_options) end def validate_security_schemes(securitySchemes) - securitySchemes.validate_security_schemes(security) + securitySchemes.each do |securityScheme| + securityScheme[1].validate_security_schemes(securityScheme[1]) + end + #securitySchemes.validate_security_schemes(security) end end end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb index c998736..8cada59 100644 --- a/lib/openapi_parser/schemas/security_schemes.rb +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -4,11 +4,11 @@ class SecuritySchemes < Base openapi_attr_values :type, :description, :scheme openapi_attr_value :bearer_format, schema_key: :bearerFormat - def validate_security_schemes(security) - puts "Validation code is executing!" + def validate_security_schemes(securityScheme) if self.type == "http" && self.scheme == "bearer" && self.bearer_format == "JWT" # check if the JWT token is being sent and try to decode. # if JWT token does not exist or token cannot decode, then deny access + puts "Checks is done" end end end From fea000d36f12e8f2047d6990293ca8089dae8fa3 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 22 Feb 2023 08:19:02 +0800 Subject: [PATCH 09/14] add jwt validation --- lib/openapi_parser/request_operation.rb | 7 +++---- lib/openapi_parser/schemas/operation.rb | 9 ++++----- lib/openapi_parser/schemas/security_schemes.rb | 9 +++++++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/openapi_parser/request_operation.rb b/lib/openapi_parser/request_operation.rb index 0004fbc..060c377 100644 --- a/lib/openapi_parser/request_operation.rb +++ b/lib/openapi_parser/request_operation.rb @@ -40,8 +40,8 @@ def initialize(http_method, result, config, security_schemes) @security_schemes = security_schemes end - def validate_security(security_schemes) - operation_object.validate_security_schemes(security_schemes) + def validate_security(security_schemes, headers) + operation_object.validate_security_schemes(security_schemes, headers) end def validate_path_params(options = nil) @@ -54,8 +54,6 @@ def validate_path_params(options = nil) # @param [OpenAPIParser::SchemaValidator::Options] options def validate_request_body(content_type, params, options = nil) options ||= config.request_body_options - - validate_security(security_schemes) operation_object&.validate_request_body(content_type, params, options) end @@ -72,6 +70,7 @@ def validate_response_body(response_body, response_validate_options = nil) # @param [OpenAPIParser::SchemaValidator::Options] options request validator options def validate_request_parameter(params, headers, options = nil) options ||= config.request_validator_options + validate_security(security_schemes, headers) operation_object&.validate_request_parameter(params, headers, options) end diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index 19e4b1c..fe03e7c 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -31,11 +31,10 @@ def validate_response(response_body, response_validate_options) responses&.validate(response_body, response_validate_options) end - def validate_security_schemes(securitySchemes) - securitySchemes.each do |securityScheme| - securityScheme[1].validate_security_schemes(securityScheme[1]) - end - #securitySchemes.validate_security_schemes(security) + def validate_security_schemes(securitySchemes, headers) + securitySchemes.each do |securityScheme| + securityScheme[1].validate_security_schemes(securityScheme[1], headers) + end end end end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb index 8cada59..f0e0d30 100644 --- a/lib/openapi_parser/schemas/security_schemes.rb +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -1,14 +1,19 @@ +require 'jwt' module OpenAPIParser::Schemas class SecuritySchemes < Base openapi_attr_values :type, :description, :scheme openapi_attr_value :bearer_format, schema_key: :bearerFormat - def validate_security_schemes(securityScheme) + def validate_security_schemes(securityScheme, headers) if self.type == "http" && self.scheme == "bearer" && self.bearer_format == "JWT" + raise "need authorization" unless headers["AUTHORIZATION"] + raise "not bearer" unless headers["AUTHORIZATION"].split[0] == "Bearer" + # check if the JWT token is being sent and try to decode. # if JWT token does not exist or token cannot decode, then deny access - puts "Checks is done" + token = headers["AUTHORIZATION"].split[1] + value = JWT.decode token, nil, false end end end From 8a778a82604575c2650559cca9baf99b960e8c27 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 22 Feb 2023 08:37:06 +0800 Subject: [PATCH 10/14] fix a bug --- lib/openapi_parser/schemas/operation.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index fe03e7c..c8a1947 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -33,7 +33,17 @@ def validate_response(response_body, response_validate_options) def validate_security_schemes(securitySchemes, headers) securitySchemes.each do |securityScheme| - securityScheme[1].validate_security_schemes(securityScheme[1], headers) + # check if the endpoint has security in schema + if security + # if security exists, check what securitySchemas used for enforcing + security.each do |s| + # securityScheme[0] is the securitySchema name + if s == securityScheme[0] + # securitySchema[1] is the values like "type", "scheme" and bearerFormat + securityScheme[1].validate_security_schemes(securityScheme[1], headers) + end + end + end end end end From f48001bfa38460e17dfacd29bf46552a50a45d2b Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Wed, 22 Feb 2023 09:36:46 +0800 Subject: [PATCH 11/14] fix tests --- lib/openapi_parser/request_operation.rb | 2 +- lib/openapi_parser/schemas/operation.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/openapi_parser/request_operation.rb b/lib/openapi_parser/request_operation.rb index 060c377..ffd6fb2 100644 --- a/lib/openapi_parser/request_operation.rb +++ b/lib/openapi_parser/request_operation.rb @@ -5,7 +5,7 @@ class << self # @param [OpenAPIParser::Config] config # @param [OpenAPIParser::PathItemFinder] path_item_finder # @return [OpenAPIParser::RequestOperation, nil] - def create(http_method, request_path, path_item_finder, config, security_schemes) + def create(http_method, request_path, path_item_finder, config, security_schemes = {}) result = path_item_finder.operation_object(http_method, request_path) return nil unless result diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index c8a1947..3bcbf9d 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -32,7 +32,7 @@ def validate_response(response_body, response_validate_options) end def validate_security_schemes(securitySchemes, headers) - securitySchemes.each do |securityScheme| + securitySchemes&.each do |securityScheme| # check if the endpoint has security in schema if security # if security exists, check what securitySchemas used for enforcing From 3c7cf65289683732a0bf1b1b1dfdb8cc1c23832c Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Fri, 24 Feb 2023 22:19:27 +0800 Subject: [PATCH 12/14] include jwt library --- openapi_parser.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openapi_parser.gemspec b/openapi_parser.gemspec index 19e739f..894cf0d 100644 --- a/openapi_parser.gemspec +++ b/openapi_parser.gemspec @@ -23,6 +23,8 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] + # production + spec.add_dependency 'jwt', '~> 1.5' spec.add_development_dependency 'bundler', '>= 1.16' spec.add_development_dependency 'fincop' From 616f0bcfd38725eca55c87a958a620823e13b9f3 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Fri, 24 Feb 2023 23:02:13 +0800 Subject: [PATCH 13/14] update code --- lib/openapi_parser/schemas.rb | 1 + lib/openapi_parser/schemas/classes.rb | 1 + lib/openapi_parser/schemas/operation.rb | 37 ++++++++++++------- lib/openapi_parser/schemas/security.rb | 7 ++++ .../schemas/security_schemes.rb | 2 +- openapi_parser.gemspec | 2 +- 6 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 lib/openapi_parser/schemas/security.rb diff --git a/lib/openapi_parser/schemas.rb b/lib/openapi_parser/schemas.rb index 562b3bf..c3bc824 100644 --- a/lib/openapi_parser/schemas.rb +++ b/lib/openapi_parser/schemas.rb @@ -17,3 +17,4 @@ require_relative 'schemas/header' require_relative 'schemas/security_schemes' require_relative 'schemas/info' +require_relative 'schemas/security' diff --git a/lib/openapi_parser/schemas/classes.rb b/lib/openapi_parser/schemas/classes.rb index a2e9902..a82dd9d 100644 --- a/lib/openapi_parser/schemas/classes.rb +++ b/lib/openapi_parser/schemas/classes.rb @@ -18,4 +18,5 @@ class Components < Base; end class Header < Base; end class SecuritySchemes < Base; end class Info < Base; end + class Security < Base; end end diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index 3bcbf9d..95f6b99 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -7,12 +7,14 @@ module OpenAPIParser::Schemas class Operation < Base include OpenAPIParser::ParameterValidatable - openapi_attr_values :tags, :summary, :description, :deprecated, :security + openapi_attr_values :tags, :summary, :description, :deprecated openapi_attr_value :operation_id, schema_key: :operationId openapi_attr_list_object :parameters, Parameter, reference: true + openapi_attr_list_object :security, Security, reference: false + # @!attribute [r] request_body # @return [OpenAPIParser::Schemas::RequestBody, nil] return OpenAPI3 object openapi_attr_object :request_body, RequestBody, reference: true, schema_key: :requestBody @@ -32,19 +34,28 @@ def validate_response(response_body, response_validate_options) end def validate_security_schemes(securitySchemes, headers) - securitySchemes&.each do |securityScheme| - # check if the endpoint has security in schema - if security - # if security exists, check what securitySchemas used for enforcing - security.each do |s| - # securityScheme[0] is the securitySchema name - if s == securityScheme[0] - # securitySchema[1] is the values like "type", "scheme" and bearerFormat - securityScheme[1].validate_security_schemes(securityScheme[1], headers) - end - end - end + validate_results = security.map do |s| # s is security requirement object + # check all security + s.validate_security_schemes(securitySchemes, headers) + end + if validate_results.count(true) == 1 + return true # accept end + return ValidateSecurityError + + # securitySchemes&.each do |securityScheme| + # # check if the endpoint has security in schema + # if security + # # if security exists, check what securitySchemas used for enforcing + # security.each do |s| + # # securityScheme[0] is the securitySchema name + # if s == securityScheme[0] + # # securitySchema[1] is the values like "type", "scheme" and bearerFormat + # securityScheme[1].validate_security_schemes(securityScheme[1], headers) + # end + # end + # end + # end end end end diff --git a/lib/openapi_parser/schemas/security.rb b/lib/openapi_parser/schemas/security.rb new file mode 100644 index 0000000..740e9cc --- /dev/null +++ b/lib/openapi_parser/schemas/security.rb @@ -0,0 +1,7 @@ +module OpenAPIParser::Schemas + class Security < Base + + def validate_security_schemes(securityScheme, headers) + end + end +end diff --git a/lib/openapi_parser/schemas/security_schemes.rb b/lib/openapi_parser/schemas/security_schemes.rb index f0e0d30..f834058 100644 --- a/lib/openapi_parser/schemas/security_schemes.rb +++ b/lib/openapi_parser/schemas/security_schemes.rb @@ -13,7 +13,7 @@ def validate_security_schemes(securityScheme, headers) # check if the JWT token is being sent and try to decode. # if JWT token does not exist or token cannot decode, then deny access token = headers["AUTHORIZATION"].split[1] - value = JWT.decode token, nil, false + JWT.decode token, nil, false end end end diff --git a/openapi_parser.gemspec b/openapi_parser.gemspec index 894cf0d..7572b7c 100644 --- a/openapi_parser.gemspec +++ b/openapi_parser.gemspec @@ -24,7 +24,7 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] # production - spec.add_dependency 'jwt', '~> 1.5' + spec.add_dependency 'jwt', '~> 2.5' spec.add_development_dependency 'bundler', '>= 1.16' spec.add_development_dependency 'fincop' From 89b7c08eac208a442c73b4693e02ddf80120e614 Mon Sep 17 00:00:00 2001 From: Muhammad Nuzaihan Date: Sat, 25 Feb 2023 00:18:24 +0800 Subject: [PATCH 14/14] cleanup --- lib/openapi_parser/errors.rb | 6 ++++++ lib/openapi_parser/schemas/operation.rb | 4 ++-- lib/openapi_parser/schemas/security.rb | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/openapi_parser/errors.rb b/lib/openapi_parser/errors.rb index 8ffddd8..f7bb585 100644 --- a/lib/openapi_parser/errors.rb +++ b/lib/openapi_parser/errors.rb @@ -272,4 +272,10 @@ def message "#{@reference} #{@value.inspect} contains fewer than min items" end end + + class ValidateSecurityError < OpenAPIError + def message + "access denied" + end + end end diff --git a/lib/openapi_parser/schemas/operation.rb b/lib/openapi_parser/schemas/operation.rb index 95f6b99..99db3a4 100644 --- a/lib/openapi_parser/schemas/operation.rb +++ b/lib/openapi_parser/schemas/operation.rb @@ -36,12 +36,12 @@ def validate_response(response_body, response_validate_options) def validate_security_schemes(securitySchemes, headers) validate_results = security.map do |s| # s is security requirement object # check all security - s.validate_security_schemes(securitySchemes, headers) + s.validate_security_requirements(securitySchemes, headers) end if validate_results.count(true) == 1 return true # accept end - return ValidateSecurityError + return OpenAPIParser::ValidateSecurityError # securitySchemes&.each do |securityScheme| # # check if the endpoint has security in schema diff --git a/lib/openapi_parser/schemas/security.rb b/lib/openapi_parser/schemas/security.rb index 740e9cc..acbf88c 100644 --- a/lib/openapi_parser/schemas/security.rb +++ b/lib/openapi_parser/schemas/security.rb @@ -1,7 +1,7 @@ module OpenAPIParser::Schemas class Security < Base - def validate_security_schemes(securityScheme, headers) + def validate_security_requirements(securityScheme, headers) end end end