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

Rework required_scopes checking #1474

Merged
merged 14 commits into from
Mar 21, 2022

Conversation

Ruwann
Copy link
Member

@Ruwann Ruwann commented Feb 23, 2022

Fixes #1423 .

Moves the required_scopes argument as current approach assumes there is one possible set of scopes per operation/security object.

I have changed the tested behaviour for this test.
If there is optional auth, if an incorrect API key is provided, the verify_none still passes and given that the security schemes are specified in OR fashion, the security check should pass.
(For example, changing the security schemes around in the spec (link) also causes the test to fail, which shouldn't happen as the order shouldn't matter)

@Ruwann Ruwann marked this pull request as draft February 23, 2022 18:25
@coveralls
Copy link

coveralls commented Mar 5, 2022

Pull Request Test Coverage Report for Build 2006287019

  • 47 of 48 (97.92%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.01%) to 96.777%

Changes Missing Coverage Covered Lines Changed/Added Lines %
connexion/security/security_handler_factory.py 32 33 96.97%
Totals Coverage Status
Change from base Build 1994636488: -0.01%
Covered Lines: 2913
Relevant Lines: 3010

💛 - Coveralls

token_info = func(request)
if token_info is not cls.no_value:
break
# TODO: Catch any error that might be raised instead of specific ones?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To check which errors should be caught here

@Ruwann Ruwann marked this pull request as ready for review March 9, 2022 19:32
@Ruwann Ruwann changed the title WIP: rework required_scopes checking Rework required_scopes checking Mar 9, 2022
@Ruwann Ruwann added this to the Connexion 2.x milestone Mar 18, 2022
Copy link
Member

@RobbeSneyders RobbeSneyders left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Ruwann! LGTM.

@RobbeSneyders RobbeSneyders merged commit 85058ed into spec-first:main Mar 21, 2022
@Ruwann Ruwann deleted the bugfix/oauth-scopes-or branch April 6, 2022 06:51
@SpudInNZ
Copy link

SpudInNZ commented Apr 11, 2022

Hi

As a result of this patch, I am quite confused about the behaviour I am now seeing. We have an API with two possible security schemes,

/accounts:
    get:
      security:
        - ApiKey: [ ]
        - OAuth2: [ accounts.read ]
....

components:
  securitySchemes:
    ApiKey:
      type: apiKey
      name: Authorization
      in: header
    OAuth2:
      type: oauth2
      flows: //etc

We have two token validation functions defined, which we specify using environment variables:

TOKENINFO_FUNC=app.security.validate_oauth2_token
APIKEYINFO_FUNC=app.security.validate_token

Calling the GET /accounts endpoint with an OAUTH token causes validate_token to be called, with required_scopes set to None. Previously this method was called, but required_scopes was set to accounts.read. Neither now nor before the patch was validate_oauth2_token ever called, which I guess is fair because in our schema both security schemes use the Authorization HTTP header (not all of our API endpoints allow both ApiKey and OAuth2, it's a backwards compatibility issue we have). The difficulty we now have, is that before we would see the required_scopes, and now we cannot.

  1. What is the expected behaviour in this scenario?
  2. Is the order of the possible security schemes in the specification important? Edit: I swapped the order to:
/accounts:
    get:
      security:
        - OAuth2: [ accounts.read ]
        -  ApiKey: [ ]

... but the behaviour is identical.
Thanks

@Ruwann
Copy link
Member Author

Ruwann commented Apr 12, 2022

Hi @SpudInNZ , I think there are two things here:

  1. Security schemes that do not have scopes (all except OAuth2 and OIDC) no longer receive any scopes in the security handler function. The reason is that the scopes are not tied to an operation, but to a certain security scheme. For example, in case an operation for example multiple sets of scopes (e.g. 2 different OAuth2 schemes that use different scopes or in addition also OIDC), there is no clear answer on what the required_scopes should be (see also Security hash maps not properly ORed when using OAuth scopes #1423 for context).

For each scheme, you specify a list of security scopes required for API calls (see below). Scopes are used only for OAuth 2 and OpenID Connect Discovery; other security schemes use an empty array [] instead.

  1. The validate_oauth2_token function never being called. I'm not sure about this one: can you create a separate issue for this with a minimal reproducible example?

In theory, the order of the security schemes doesn't matter as it's an unordered mapping. However, in practice, connexion will first check the first security scheme, if that succeeds, we're done. If that fails, the second security scheme is checked. So it could have some impact depending on the performance if one function is more expensive than the other.

@vashek
Copy link

vashek commented Apr 5, 2023

@SpudInNZ Did you ever find a good solution to this? This broke my app, too.

(It's a bit frustrating TBH: upgrading from an (admittedly old) 2.x.x release, I've bumped into two separate breaking changes not clearly marked as breaking (this one and #1265 which I've already worked around). Sorry for complaining about an otherwise great open source project that I got for free.)

@Ruwann
Copy link
Member Author

Ruwann commented Apr 8, 2023

Hi @vashek , we try to limit the breaking changes as much as possible, but we didn't anticipate breaking behaviour from this patch.
We had a discussion on this sort of cases, as this fixes a bug in connexion that led to this behaviour and whether to bump the major version.
What would have the ideal case for you here? Then we can see if and how we can do better in the future :)

To go further on what you aim to achieve and how it is breaking your application: as discussed in the comment above, there is undefined behaviour when there are multiple security schemes for which scopes are defined. For example,

security:
    - oauth: [ read ]
    - oauth: [ admin ]
    - api_key: []

I don't see a clear answer to what should happen in this case. What would you like to happen here?
Note that this might be solved in OpenAPI 3.1, as there the scopes can also be defined for schemes other than OAuth2 and OIDC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Security hash maps not properly ORed when using OAuth scopes
5 participants