Search code examples
pythondjangoswaggerdjango-swagger

Django REST Swagger: How to use security section in Swagger settings?


I'm trying to build the Swagger settings for SecurityDefinition in order to get the following result in openapi.json:

"securityDefinitions": {
  "password": {
    "type": "oauth2",
    "tokenUrl": "http://example.com/oauth/token",
    "flow": "password",
    "scopes": {
      "write": "allows modifying resources",
      "read": "allows reading resources"
    }
  }
},
"security": [{
  "password": ["read", "write"]
}]

In my settings.py I have addded the following swagger settings:

# Swagger settings
SWAGGER_SETTINGS = {
  "SECURITY_DEFINITIONS": {
    "password": {
        "type": "oauth2",
        "tokenUrl": "http://example.com/oauth/token",
        "flow": "password",
        "scopes": {
            "write": "allows modifying resources",
            "read": "allows reading resources"
        }
     }
  },
  "SECURITY": [{
    "password": ["read", "write"]
  }]
}

The issue is that in the openapi.json which generated by Swagger there is not the security dict and I have no clue how it is generated.

Below, presented the generated openapi.json:

{
   "info": {
       "title": "Example Service API",
       "version": ""
   },
   "host": "http://example.com",
   "swagger": "2.0",
   "securityDefinitions": {
       "password": {
           "type": "oauth2",
           "scopes": {
               "write": "allows modifying resources",
               "read": "allows reading resources"
           },
           "tokenUrl": "http://example.com/oauth/token",
           "flow": "password"
       }
   },
   "paths": {...}
}

Is there any better way to describe this concept in my Swagger settings? Or can you describe me which is the process and how it is working in order to generate the openapi.json file?


Solution

  • When in doubt, check the code. You can see the definition of OpenAPIRenderer here:

    class OpenAPIRenderer(BaseRenderer):
        media_type = 'application/openapi+json'
        charset = None
        format = 'openapi'
    
        def render(self, data, accepted_media_type=None, renderer_context=None):
            if renderer_context['response'].status_code != status.HTTP_200_OK:
                return JSONRenderer().render(data)
            extra = self.get_customizations()
    
            return OpenAPICodec().encode(data, extra=extra)
    
        def get_customizations(self):
            """
            Adds settings, overrides, etc. to the specification.
            """
            data = {}
            if swagger_settings.SECURITY_DEFINITIONS:
                data['securityDefinitions'] = swagger_settings.SECURITY_DEFINITIONS
    
            return data
    

    So one way to do this is to subclass, for example:

    class MyOpenAPIRenderer(OpenAPIRenderer):
        def get_customizations(self):
            data = super().get_customizations()
    
            # your customizations
            data["security"] = swagger_settings.SECURITY
    
            return data
    

    Then you can use this renderer class for your view. Hope it helps!