Skip to content

[BUG][python-fastapi] API route handler does not pass OAuth2 TokenModel to implementation #20048

@micolous

Description

@micolous

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

OpenAPI Generator's generated Python-FastAPI code works by your implementation subclassing a base API module, and then the generated router module (ie: apis/pet_api.py) calls one of the subclasses of a base API module (ie: apis/pet_api_base.py).

The generated router method a reference to a TokenModel (token_petstore_auth), but this is attribute is never passed to the subclass add_pet() implementation:

async def add_pet(
pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")] = Body(None, description="Pet object that needs to be added to the store"),
token_petstore_auth: TokenModel = Security(
get_token_petstore_auth, scopes=["write:pets", "read:pets"]
),
) -> Pet:
""""""
if not BasePetApi.subclasses:
raise HTTPException(status_code=500, detail="Not implemented")
return await BasePetApi.subclasses[0]().add_pet(pet)

That code is generated here, where there is no reference to {{#authMethods}} in the method body, only {{#allParams}}:

token_{{name}}: TokenModel = Security(
get_token_{{name}}{{#isOAuth}}, scopes=[{{#scopes}}"{{scope}}"{{^-last}}, {{/-last}}{{/scopes}}]{{/isOAuth}}
),
{{/authMethods}}
{{/hasAuthMethods}}
) -> {{returnType}}{{^returnType}}None{{/returnType}}:
{{#notes}}"""{{.}}"""
{{/notes}}if not Base{{classname}}.subclasses:
raise HTTPException(status_code=500, detail="Not implemented")
return await Base{{classname}}.subclasses[0]().{{operationId}}({{#allParams}}{{>impl_argument}}{{^-last}}, {{/-last}}{{/allParams}})

And the TokenModel doesn't appear in the base API module (ie: apis/pet_api_base.py):

def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
BasePetApi.subclasses = BasePetApi.subclasses + (cls,)
async def add_pet(
self,
pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")],
) -> Pet:
""""""
...

That code is generated here, where there is no reference to {{#authMethods}} at all:

{{#operation}}
async def {{operationId}}(
self,
{{#allParams}}
{{>impl_argument_definition}},
{{/allParams}}
) -> {{returnType}}{{^returnType}}None{{/returnType}}:

As a result, it is impossible to use the validated information from the OAuth token in your implementation.

Expected behaviour

The base API should include the TokenModel:

class BasePetApi:
    # ...
    async def add_pet(
        self,
        pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")],
        token_petstore_auth: TokenModel = Security(
            get_token_petstore_auth, scopes=["write:pets", "read:pets"]
        ),
    ) -> Pet:
        """"""
        ...

The generated router method should pass on the TokenModel:

# ...
async def add_pet(
    pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")] = Body(None, description="Pet object that needs to be added to the store"),
    token_petstore_auth: TokenModel = Security(
        get_token_petstore_auth, scopes=["write:pets", "read:pets"]
    ),
) -> Pet:
    """"""
    if not BasePetApi.subclasses:
        raise HTTPException(status_code=500, detail="Not implemented")
    return await BasePetApi.subclasses[0]().add_pet(pet, token_petstore_auth)

That way, your implementation can use the token with something like:

class PetApiImpl(BasePetApi):
    # ...
    async def add_pet(self, pet: Pet, token_petstore_auth: TokenModel):
        database.Pet.objects.create(creator=token_petstore_auth.sub, pet=pet)
openapi-generator version

7.9.0

OpenAPI declaration file content or url

/pet:
post:
description: ""
operationId: addPet
requestBody:
$ref: '#/components/requestBodies/Pet'
responses:
"200":
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
description: successful operation
"405":
description: Invalid input
security:
- petstore_auth:
- write:pets
- read:pets
summary: Add a new pet to the store
tags:
- pet

Generation Details

Sample is included with OpenAPI Generator:

./bin/generate-samples.sh ./bin/configs/*.yaml
Steps to reproduce
Related issues/PRs
Suggest a fix

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions