diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 1c7a17c4ca..21b536766b 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -82,24 +82,23 @@ def get_openapi_security_definitions( flat_dependant: Dependant, ) -> tuple[dict[str, Any], list[dict[str, Any]]]: security_definitions = {} - # Use a dict to merge scopes for same security scheme - operation_security_dict: dict[str, list[str]] = {} + # Use a dict of sets to merge scopes for same security scheme + operation_security_dict: dict[str, set[str]] = {} for security_dependency in flat_dependant._security_dependencies: - security_definition = jsonable_encoder( - security_dependency._security_scheme.model, - by_alias=True, - exclude_none=True, - ) security_name = security_dependency._security_scheme.scheme_name - security_definitions[security_name] = security_definition - # Merge scopes for the same security scheme + if security_name not in security_definitions: + security_definition = jsonable_encoder( + security_dependency._security_scheme.model, + by_alias=True, + exclude_none=True, + ) + security_definitions[security_name] = security_definition if security_name not in operation_security_dict: - operation_security_dict[security_name] = [] + operation_security_dict[security_name] = set() for scope in security_dependency.oauth_scopes or []: - if scope not in operation_security_dict[security_name]: - operation_security_dict[security_name].append(scope) + operation_security_dict[security_name].add(scope) operation_security = [ - {name: scopes} for name, scopes in operation_security_dict.items() + {name: sorted(scopes)} for name, scopes in operation_security_dict.items() ] return security_definitions, operation_security