Repository: pulp/pulpcore

Issue:
Include SecurityScheme for the external auth in the OpenAPI schema 
**Is your feature request related to a problem? Please describe.**
We are using the `JSONHeaderRemoteAuthentication` backend to authenticate users. The authentication actually occurs before the request is routed to Pulp. The OpenAPI schema currently states that Basic and Session auth are supported. There is no way for `pulp-cli` to know that it can use `OAuth2`  to authenticate with this Pulp server.

**Describe the solution you'd like**
`REMOTE_AUTH_OPENAPI_SECURITY_SCHEME`  setting which would need to be a Python dictionary or a JSON object that looks like this:

```
  {"oAuth2": {
    "type": "oauth2",
    "description": "External OAuth integration",
    "flows": {
      "clientCredentials": {
        "tokenUrl": "https://sso.mycompany.com/auth/realms/company-external/protocol/openid-connect/token",
        "scopes": {
          "api.console": "Grant access to Pulp"
        }
      }
    }
  }
```

The top key is the `name` of the security scheme. The whole data structure should look like a full securityScheme that would appear in the OpenAPI schema. 


Discussion:

Resolving patch:
diff --git a/pulpcore/app/settings.py b/pulpcore/app/settings.py
--- a/pulpcore/app/settings.py
+++ b/pulpcore/app/settings.py
@@ -256,6 +256,7 @@
 
 AUTHENTICATION_JSON_HEADER = ""
 AUTHENTICATION_JSON_HEADER_JQ_FILTER = ""
+AUTHENTICATION_JSON_HEADER_OPENAPI_SECURITY_SCHEME = {}
 
 ALLOWED_IMPORT_PATHS = []
 
@@ -407,6 +408,16 @@
     authentication_json_header_validator & authentication_json_header_jq_filter_validator
 )
 
+authentication_json_header_openapi_security_scheme_setting_validator = Validator(
+    "AUTHENTICATION_JSON_HEADER_OPENAPI_SECURITY_SCHEME", len_min=1
+)
+authentication_json_header_openapi_security_scheme_validator = Validator(
+    "AUTHENTICATION_JSON_HEADER_OPENAPI_SECURITY_SCHEME",
+    when=authentication_json_header_openapi_security_scheme_setting_validator,
+    is_type_of=dict,
+    messages={"is_type_of": "{name} must be a dictionary."},
+)
+
 settings = DjangoDynaconf(
     __name__,
     ENVVAR_PREFIX_FOR_DYNACONF="PULP",
@@ -424,6 +435,7 @@
         storage_validator,
         unknown_algs_validator,
         json_header_auth_validator,
+        authentication_json_header_openapi_security_scheme_validator,
     ],
 )
 # HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line)
diff --git a/pulpcore/openapi/__init__.py b/pulpcore/openapi/__init__.py
--- a/pulpcore/openapi/__init__.py
+++ b/pulpcore/openapi/__init__.py
@@ -22,6 +22,7 @@
 from drf_spectacular.settings import spectacular_settings
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.utils import OpenApiParameter, extend_schema_field
+from drf_spectacular.extensions import OpenApiAuthenticationExtension
 from rest_framework import mixins, serializers
 from rest_framework.exceptions import ParseError
 from rest_framework.schemas.utils import get_pk_description
@@ -518,3 +519,11 @@ def get_schema(self, request=None, public=False):
         result["servers"] = [{"url": server_url}]
 
         return normalize_result_object(result)
+
+
+class JSONHeaderRemoteAuthenticationScheme(OpenApiAuthenticationExtension):
+    target_class = "pulpcore.app.authentication.JSONHeaderRemoteAuthentication"
+    name = "json_header_remote_authentication"
+
+    def get_security_definition(self, auto_schema):
+        return settings.AUTHENTICATION_JSON_HEADER_OPENAPI_SECURITY_SCHEME


Test patch:
diff --git a/pulpcore/tests/functional/api/test_openapi_schema.py b/pulpcore/tests/functional/api/test_openapi_schema.py
--- a/pulpcore/tests/functional/api/test_openapi_schema.py
+++ b/pulpcore/tests/functional/api/test_openapi_schema.py
@@ -86,3 +86,22 @@ def test_no_dup_operation_ids(pulp_openapi_schema):
 
     dup_ids = [id for id, cnt in operation_ids.items() if cnt > 1]
     assert len(dup_ids) == 0, f"Duplicate operationIds found: {dup_ids}"
+
+
+@pytest.mark.parallel
+def test_external_auth_on_security_scheme(pulp_settings, pulp_openapi_schema):
+    if (
+        "django.contrib.auth.backends.RemoteUserBackend"
+        not in pulp_settings.AUTHENTICATION_BACKENDS
+        and "pulpcore.app.authentication.JSONHeaderRemoteAuthentication"
+        not in pulp_settings.REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"]
+    ):
+        pytest.skip(
+            "Test can't run unless RemoteUserBackend and JSONHeaderRemoteAuthentication are enabled"
+        )
+
+    security_schemes = pulp_openapi_schema["components"]["securitySchemes"]
+    assert "json_header_remote_authentication" in security_schemes
+
+    security_scheme = security_schemes["json_header_remote_authentication"]
+    assert pulp_settings.AUTHENTICATION_JSON_HEADER_OPENAPI_SECURITY_SCHEME == security_scheme