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

One security requirement satisfied, and another hard-failing #1698

Closed
jwalton opened this issue Oct 1, 2018 · 8 comments
Closed

One security requirement satisfied, and another hard-failing #1698

jwalton opened this issue Oct 1, 2018 · 8 comments
Labels
security: auth Authentication including overlap with authorization security

Comments

@jwalton
Copy link
Contributor

jwalton commented Oct 1, 2018

@niallmccullagh and I were having a discussion over here which I've had more than once with a few people, and everyone has a different opinion about how this scenario should work. Let's suppose you have a security requirement that looks like:

security:
  - session: []
  - basicAuth: []

So to access this operation, you either need a valid session key, or a valid basic auth header.

Now, let's suppose a client sends a valid session key, but also sends a basic auth header with a username but the incorrect password. The question is:

  • Should the server reject this request, because according to the principal of least privilege, we have a user with a bad password who shouldn't be allowed to access anything?
  • Should the server allow this request, because according to the spec "When a list of Security Requirement Objects is defined on the Open API object or Operation Object, only one of Security Requirement Objects in the list needs to be satisfied to authorize the request," and therefore the request should be satisfied?
@MikeRalphson
Copy link
Member

Possibly related #971

@cmheazel
Copy link
Contributor

cmheazel commented Oct 4, 2018

"Security Requirement Objects that contain multiple schemes require that all schemes MUST be satisfied for a request to be authorized."
Security elements are arrays of Security Requirement Objects. Only one of the requirements in an array needs to be satisfied to grant access. All of the schemes within a requirement must be satisfied to satisfy that requirement. This gives us a nice way to construct AND / OR relationships.

@jwalton
Copy link
Contributor Author

jwalton commented Oct 4, 2018

@cmheazel If your Security Requirement Object says "A or B", and A is present and B is not, then clearly the requirement is satisfied. I understand that part. If A and B are both present, it's similarly obvious the requirement is satisfied.

But if the requirement is "A or B" and A and B are both present, and A is incorrect, is the requirement satisfied? By the letter of the spec, it is, because B is present and correct. I would argue this is incorrect, however. The client is trying to authenticate as A and is failing, so something is not right here.

@cmheazel
Copy link
Contributor

cmheazel commented Oct 4, 2018

Let's start with Example 1:

openapi: 3.0.1 security: - securityRqmt1: - scheme1 - securityRqmt2: - scheme2

There are two security requirements, each with one scheme. Access is allowed if either scheme1 or scheme2 is valid.

Next we look at example 2:

openapi: 3.0.1 security: - securityRqmt3: - scheme3 - scheme4

In this case we have one security requirement which contains two schemes. Access is allowed only if both scheme3 and scheme4 are valid.

Finally we bring it all together in example 3:

openapi: 3.0.1 security: - securityRqmt1: - scheme1 - securityRqmt2: - scheme2 - securityRqmt3: - scheme3 - scheme4

Access is governed by the following Boolean expression:
scheme1 OR scheme2 OR (scheme3 AND scheme4)

Does that help?

@jwalton
Copy link
Contributor Author

jwalton commented Oct 4, 2018

Maybe a table will help.

Let's say we're in example 1. Access is allowed if scheme1 is valid or scheme2 is valid.

A given security requirement can be in one of three states; valid, missing, or invalid. For example, if you need a basic auth header, the auth header can not be there at all (missing), it can be there with a valid username and password (valid), or it can be there, but have an invalid username, or valid username but the wrong password (invalid).

s1 valid s1 missing s1 invalid
s2 valid allow allow ???
s2 missing allow reject reject
s2 invalid ??? reject reject

These "???"s are the bit I'm concerned with. You assertion is that, in the upper right corner here, even though the user has provided invalid credentials for scheme1, we should still allow the request through, because they provided valid credentials for scheme2, and since this satisfies the boolean logic "s1 || s2", we're good.

My assertion is that an invalid credential should be treated less like a false and more like a throw new Error("Wat?"). I think we should reject in this case; because the client is clearly providing you with nonsense and doesn't know what it's doing.

My implementation does exactly this second one, but I've had this same discussion many times, and I always come to a different conclusion about how it should be handled. :)

@cmheazel
Copy link
Contributor

cmheazel commented Oct 5, 2018

"When a list of Security Requirement Objects is defined on the Open API object or Operation Object, only one of Security Requirement Objects in the list needs to be satisfied to authorize the request."
The way I would address this requirement is:

IF securityRqmt1 is present and scheme1 is valid THEN allow access
ELSE
IF securityRqmt2 is present and scheme2 is valid THEN allow access
ELSE disallow access

So the value for ???? should be "allow" since one of the security requirements was satisfied.
Note that this does not prevent a security scheme from implementing the throw new Error("what?") response. But that level of detail resides in the authentication protocol, not is the OAS document.

@jwalton
Copy link
Contributor Author

jwalton commented Oct 28, 2018

Ah, but, in your implementation our truth table ends up looking like:

s1 valid s1 missing s1 invalid
s2 valid allow allow reject
s2 missing allow reject reject
s2 invalid allow reject reject

One of the ??? becomes allow (because we check s1 first), but the second becomes a reject (because we catch the error from s2). This gives us a truth table that is weirdly not symmetric. It also implies that the ordering of security requirements is significant, which I'm not sure the spec implies.

@LasneF
Copy link
Member

LasneF commented Oct 3, 2024

closing this one as not so munch activity ,
will be managed in this most recent
#4119

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
security: auth Authentication including overlap with authorization security
Projects
None yet
Development

No branches or pull requests

5 participants