Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly state what security: [] means #3995

Closed

Conversation

rvedotrc
Copy link

@rvedotrc rvedotrc commented Aug 5, 2024

It's currently not clear from the spec what security: [] means. It's stated that it's allowed, but it doesn't say what it does. Obvious guesses are that it either authorizes everything, or that it authorizes nothing; but it's not stated which.

As per #3938, I'm told that the answer is "authorize everything"; so this PR seeks to make that explicit.

On the other hand, if that answer is incorrect, please let me know what [] in fact means, and I'll see if I can update this PR accordingly.

See also: #3994

@rvedotrc rvedotrc marked this pull request as ready for review August 5, 2024 13:35
@handrews handrews added security security: config The mechanics of severs and structure of security-related objects labels Aug 5, 2024
@ralfhandl
Copy link
Contributor

As @rvedotrc correctly points out

If one is going to define AND/OR for zero operands, then conventionally one defines AND-of-nothing to be true, and OR-of-nothing to be false.

This would indicate that an empty array is not a synonym for an array containing an empty object, but rather "no way to authenticate here".

On the other hand 3.1.0 states

This definition overrides any declared top-level security. To remove a top-level security declaration, an empty array can be used.

I'd rather remove/undefine/nullify a top-level security declaration with security: null.

@rvedotrc
Copy link
Author

rvedotrc commented Aug 5, 2024

Additional observations:

https://spec.openapis.org/oas/latest.html#schema "In the following description, if a field is not explicitly REQUIRED or described with a MUST or SHALL, it can be considered OPTIONAL."

In https://spec.openapis.org/oas/latest.html#fixed-fields , security is not marked as required / must / shall. Therefore, it's optional. If security is not provided (because it's absent? because it's present, but null?), then what is the behaviour? We are not told. Again, obvious guesses are "deny all" and "allow all", but it would be nice not to have to guess.

@ralfhandl
Copy link
Contributor

If security is not provided (because it's absent? because it's present, but null?), then what is the behaviour?

My guess: if security is not provided in the OpenAPI Object, this means "we don't tell you", and the client can assume nothing. If it is present with value null, this means "we tell you that we don't tell you", and the client again can assume nothing.

@handrews
Copy link
Member

handrews commented Aug 5, 2024

@ralfhandl if it's this confusing, we might need to clarify in 3.0.4/3.1.1 (or at least acknowledge that the behavior is undefined).

To me, this part:

This definition overrides any declared top-level security. To remove a top-level security declaration, an empty array can be used.

means that empty arrays == there are no conditions to meet == there are no security checks. Why else would you remove existing checks entirely? And a [] should mean the same anywhere, not just when it's used to override.

@rvedotrc
Copy link
Author

rvedotrc commented Aug 6, 2024

If it is present with value null

AFAICT, the word null appears precisely once in the 3.1.0 spec, and it's not in this context. Therefore, either this field cannot (currently) be null, or it can be null (presumably on account of being OPTIONAL), but in which case it would be helpful to explain that OPTIONAL means "can be present, but null".

and/or perhaps OPTIONAL means "can be absent".

Also, if present-but-null is allowed, then is that different from being absent? How about in the operation.security case?

I detect a can of worms. :-/

@rvedotrc
Copy link
Author

rvedotrc commented Aug 6, 2024

To summarise what we've got so far, from my point of view:

Optionality:

  1. The meaning of OPTIONAL is not well-defined. Obvious guesses are that it means "may be absent" and/or "may be present, but null"; it would be helpful to explain which of these three is in fact the case.
  2. If an OPTIONAL field may be present-but-null (see point 1), we should define whether or not that null overrides higher values (e.g. in the case of Operation.security). This could be defined at the schema level (i.e. add it just after the explanation of OPTIONAL here), or (more messily) for each applicable field.
  3. Perhaps it would be helpful clearly to state, for each optional field, what the meaning is if the field is absent / present-but-null (see point 1). But here the can of worms is getting even bigger.

The security field:

  1. It would be helpful to define what absent / present-but-null means (at the OAS level)
  2. It would be helpful to define what absent / present-but-null means (at the Operation level)
  3. It would be helpful to define what [] means (at either level)
  4. AFAICT, the meaning of [] is currently not defined; I can see why people would assume it to mean "authorize all", mostly because it "looks like" [{}] (they're both empty, right?); but using the normally-accepted rules of boolean set logic, it would mean "deny all".

@ralfhandl
Copy link
Contributor

ralfhandl commented Aug 6, 2024

I fully agree with @rvedotrc that this looks like a can of worms 🪱 😢.

Current text for security on the OAD level

  • Version 2.0

    The list of values describes alternative security schemes that can be used (that is, there is a logical OR between the security requirements).

  • Versions 3.0.0 to 3.1.0

    Only one of the security requirement objects need to be satisfied to authorize a request.

  • Versions 3.0.3 and 3.1.0 add

    To make security optional, an empty security requirement ({}) can be included in the array.

To me this means: an empty list does not contain a security requirement object that can be satisfied, so there is no way to authorize the request.

This is further supported by the 2.0 mentioning of logical OR, because OR over an empty list of conditions is false.

It is also supported by the additional text in 3.0.3 and 3.1.0 recommending to add true to the list of conditions instead of defining special (and unusual) meaning for the empty list.

Current text for security on the operation object level

  • all versions

    This definition overrides any declared top-level security. To remove a top-level security declaration, an empty array can be used.

For me this is in line with the above interpretation:

  • If an operation has specific security, one can list all allowed security requirement objects, including the case of "none are allowed".

@rvedotrc
Copy link
Author

rvedotrc commented Aug 6, 2024

So ... should I update the PR contents so as to explain that security: [] means "there is no way to authorize"?

@ralfhandl
Copy link
Contributor

ralfhandl commented Aug 6, 2024

So ... should I update the PR contents so as to explain that security: [] means "there is no way to authorize"?

In my humble opinion: yes.

Let's wait for others to state their opinion, here or in one of the next TDC calls.

@rvedotrc do you want to dial in? The discussion is open for everyone.

@rvedotrc
Copy link
Author

rvedotrc commented Aug 6, 2024

1600 UTC, right? Sure :-)

@ralfhandl
Copy link
Contributor

Correct, 18:00-19:00 CEST 😁

@miqui
Copy link
Contributor

miqui commented Aug 8, 2024

For what its worth:
An empty array in the security field indicates that no security schemes are applied to the specific operation. This means the endpoint can be accessed without any authentication or authorization. Inline with (3.0.3 and 3.1.0):

To make security optional, an empty security requirement ({}) can be included in the array.

and its override use cases at both the root or operation level.

My humble interpretation of security not being present at all is simple: You did not define any form of security scheme, so therefore the entire API is not secured in any way (perhaps this is your requirement).

I rather not go down the nullish rabbit hole unless we feel IT IS ABSOLUTELY necessary for both humans and code.

@ralfhandl
Copy link
Contributor

We have three cases to consider:

  1. no security
  2. security: []
  3. security: [{}]

Only the third case is explicitly mentioned in the specs:

To make security optional, an empty security requirement ({}) can be included in the array.

I would not assume that 1 and 2 are synonyms of 3.

@lornajane
Copy link
Contributor

Things we do agree on (from TDC):

  • if security is not defined, then we assume "allow all" for all operations
  • if the security array has entries, one of those entries must be satisfied for a request to be authorised

The correct behaviour for an empty array is unclear. We think it is widely used to mean that there's no security applied ("allow all") - but logically it means that there are no security rules that can be fulfilled to permit access.

We do need to update wording to explain that the empty security array is ambiguous in the current spec versions.

@handrews
Copy link
Member

handrews commented Aug 8, 2024

I did some digging, and found that @webron added the "To remove a top-level security declaration, an empty array can be used." in this Swagger/OAS 2.0 commit. I have not been able to find any further information on whether "remove" meant "default back to deny-all" or "default back to allow-all". Since this is 2.0, which was initially developed within Swagger, I checked their site but was unable to find any further information on security: [].

Arguably, since this language was added pre-OpenAPI, it would be valid to look at how Swagger handles an empty array for insight into the original intent. I normally dislike using Swagger as a reference point as OpenAPI is long since a distinct entity, but this has not changed since it was added for 2.0.

I do think that the fact that {} was explicitly described as a way to make security optional suggests that maybe "remove" meant deny-all, but ¯\(ツ)(yes, this is different from what I originally thought in #3938) but we have to take the current tool behavior and dependencies into account.

@ralfhandl ralfhandl added this to the v3.2.0 milestone Aug 19, 2024
@ralfhandl ralfhandl marked this pull request as draft August 29, 2024 08:36
@ralfhandl
Copy link
Contributor

Changed to draft: needs to be merged after #4035 as it changes contents of table cells and will conflict with our markdown cleanup.

@handrews
Copy link
Member

In today's TDC we agreed to re-try this based on @mikekistler 's "open world" view, so closing these three attempts.

@rvedotrc thank you for your contributions here- it is far from the first topic where we've had to go through multiple approaches, attempts, and PRs. Regardless of who writes the final PR, this has helped us immensely in figuring the problem out.

@handrews handrews closed this Aug 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
security: config The mechanics of severs and structure of security-related objects security
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants