Hi Team, We are using pactflow for bi-directional...
# pactflow
b
Hi Team, We are using pactflow for bi-directional contract testing. We have a provider oas file in that we have defined security schema as OAuth2 and we did not specify Authentication header in open api specification file. But when we send Authentication headers in consumer contract validation succeeded. If we specify any other header in the consumer contract other than Authentication it is getting failed. why pactflow is only ignoring the Authentication header in the consumer contract.
šŸ‘‹ 1
m
Hi there, unfortunately I’m going to need a little more information to help you. Could you elaborate with a minimal example to highlight the problem?
b
Copy code
Hi @Matt (pactflow.io / pact-js / pact-go)  Thanks for the response.  openapi: 3.0.3
info:
  title: Reqres - OpenAPI 3.0
  version: 1.0.0
servers:
  - url: '<https://reqres.in/api>'
paths:
  /register:
    post:
      tags:
        - register
      operationId: register
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Register'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegisterResponse'
components:
  schemas:
    Register:
      type: object
      properties:
        username:
          type: string
          example: username
        email:
          type: string
          example: john.doe@email.com
        password:
          type: string
          example: password
        object:
          $ref: '#/components/schemas/InnerRequestObject'
      additionalProperties: false
    InnerRequestObject:
      type: object
      properties:
        street:
          type: string
          example: 305 Joe st
        Postcode:
          type: number
          example: 54679
      additionalProperties: false
    RegisterResponse:
      type: object
      properties:
        error:
          type: string
          example: string
  securitySchemes:
    openId:   # <--- Arbitrary name for the security scheme. Used to refer to it from elsewhere.
      type: openIdConnect
      openIdConnectUrl: <https://example.com/.well-known/openid-configuration>
security:
  - openId: []
We have a openapi spec file like i mentioned above and it does not have any Authorization headers mentioned and if i send Authorization header in Consumer contract pactflow contract validation is getting passed. Why ?
m
Mind reformatting the above with triple backticks? (or use the code block format option)? All of the bullet poitns are a bit distracting
b
Can you please check now. @Matt (pactflow.io / pact-js / pact-go)
t
Is this due to the root level
security
definition? Since it applies to all operations/requests by default. I think this would mean
Authorization
is expected, even if this header is not explicitly defined per operation
ā˜ļø 1
b
I can see consumer contract validation is getting passed without sending any Authorization header.
m
What are the errors you’re seeing? It’s a bit theoretical at the moment
See https://docs.pactflow.io/docs/bi-directional-contract-testing/contracts/oas/features#security-schemes for the support
But when we send Authentication headers in consumer contract validation succeeded. If we specify any other header in the consumer contract other than Authentication it is getting failed
it’s not ignoring the Auth header, it’s checking that one exists, without checking the contents of it. It’s erroring on other headers (presumably) as they are not defined in the OAS. I’d need to see the errors though
b
Hi Matt , I do not see any error when I am sending the Authorization header. I do not see any error if I do not send Authorization headers. how is this possible.
m
Please share the errors
t
I think the issue is the lack of errors šŸ˜„ It roughly sounds like the presence of the
security
definition creates an expectation for an
Authorization
header but it is not being treated as a hard requirement, so contract comparison is passing regardless of whether the consumer's contract contains it or not
āœ… 1
b
Oh okay Thanks Ty šŸ™
t
I suppose one "fix" would be to explicitly define it, per operation, like:
Copy code
parameters:
  - name: Authorization
    in: header
    required: true
    schema:
      type: string
While this would probably fix the contract test(s), I'm not 100% sure what else it will impact (e.g. testing through the Swagger Editor made awkward) There may be a better way though, so hopefully someone more familiar than me can provide a more elegant solution šŸ™‚
b
Thanks Ty we will try this. šŸ™‚
m
I can’t reproduce the ā€œerrorā€ if other headers are provided, but I can produce a warning. That makes sense, because Authorization is in the file and globally defined. I understand the counterpoint though and will investigate
Thanks for raising. I do believe this should have produced visible errors/warnings in the PactFlow UI, if this is not the case, please confirm as that is definitely a bug
b
Oh okay Thanks Matt
Copy code
I do have have one more issue while validating above openapi spec file with below consumer contract   {
  "provider": {
    "name": "example-provider"
  },
  "consumer": {
    "name": "example-consumer"
  },
  "interactions": [
    {
      "description": "description",
      "providerState": "provider state",
      "request": {
        "method": "POST",
        "path": "/register",
        "headers": {
          "Content-Type": "application/json; charset=utf-8"
        },
        "body": {
          "username": "username",
		  "email": "<mailto:john.doe@email.com|john.doe@email.com>",
		  "password": "password",
		  "Key": "Value",
		   InnerRequestObject: {
			   "Street": "305 Joe st",
			   "Postcode": 54679
		   } 
        },
        "matchingRules": {
          "headers": {
            "$.Content-Type": {
              "match": "regex",
              "regex": "/^application/json; charset=utf-8$/"
            }
          }
        }
      },
      "response": {
        "status": 200
      }
    }
  ],
  "metadata": {
    "pactSpecificationVersion": "2.0.0"
  }
}
It is throwing an error Request boday is incomapatable with request body schema in the spec file : must NOT have additionalProperties . But when remove additionalProperties: false attribute for Register object validation passed with out any issues.
If we remove the additionalProperties: false attribute for Register object and consumer is sending any extra object inside Register object it may lead to in comaptible issue in production. Can you please suggest how to procceed on this ? @Matt (pactflow.io / pact-js / pact-go)
m
If there are additional properties that shouldn't be there (and you know that would be unsafe), shouldn't you address that problem? In any case, we automatically close the schema: https://docs.pactflow.io/docs/bi-directional-contract-testing/contracts/oas/keyword-support#transformations-pactflow-applies-to-openapi-documents
Again, it would really help to have the OAS and pact file that's problematic or a minimal repro
b
Hi @Matt (pactflow.io / pact-js / pact-go) Please find the github repo. when i tried to validate the uploaded contract.json with openapi spec file with swagger-mock-validator it is throwing an error ( Request boday is incomapatable with request body schema in the spec file : must NOT have additionalProperties) - We are getting same error in PactFlow. Github Link : https://github.com/gnanendra-bogireddy/pactflow-compatibility-check
@Matt (pactflow.io / pact-js / pact-go) Good Morning. Is there any update on this ? Thanks
m
Thanks for creating the repro.
additionalProperties: true
is allowed on request bodies, as this supports Postel’s law. > it may lead to in comaptible issue in production No, not necessarily. The real problem is that your OAS (in the example, at least) is not very well defined. As all the fields are optional, this indeed could cause problems in production because any properties will pass that test. What you should do, is define schemas with the minimal required fields - this would fail the comparison, but for the right reasons. Additional properties in the request aren’t problematic (you can choose to disable this of course), but what is problematic is if the consumer doesn’t send the minimum right properties in the request. The real issue is that your Pact contract doesn’t match the schema, and that your OAS isn’t enforcing the schema itself (via required). Here’s how to fix it… The real issue is that your Pact contract doesn’t match the schema, and that your OAS isn’t enforcing the schema itself (via
required
). Your example:
Copy code
{
  "username": "username",
  "email": "john.doe@email.com",
  "password": "password",
  "Key": "Value",
  "InnerRequestObject": {
    "Street": "305 Joe st",
    "Postcode": 54679
  }
}
Correct example:
Copy code
{
  "username": "username",
  "email": "john.doe@email.com",
  "password": "password",
  "object": {
    "street": "305 Joe st",
    "postcode": 54679
  }
}
Setting required properties on the schemas:
Copy code
components:
  schemas:
    Register:
      type: object
      required:
        - username
        - email
        - password
        - object
      properties:
        username:
          type: string
          example: username
        email:
          type: string
          example: john.doe@email.com
        password:
          type: string
          example: password
        object:
          $ref: '#/components/schemas/InnerRequestObject'
    InnerRequestObject:
      type: object
      required:
        - street
        - postcode
      properties:
        street:
          type: string
          example: 305 Joe st
        postcode:
          type: number
          example: 54679
Example error if
object
is not provided, even with additional properties being sent:
Copy code
Request body is incompatible with the request body schema in the spec file: must have required property 'object'
b
Thanks @Matt (pactflow.io / pact-js / pact-go) for detailed description on how to resolve the error. . šŸ™
šŸ™Œ 1