jpadilla / pyjwt

JSON Web Token implementation in Python
https://pyjwt.readthedocs.io
MIT License
5.05k stars 676 forks source link

Wrong return type for createMyTokenObtainPair in OpenAPI schema #841

Closed rbuffat closed 1 year ago

rbuffat commented 1 year ago

When generating an OpenAPI schema using python manage.py generateschema, the schema for the request to /api/token/ is generated as follows:

  /api/token/:
    post:
      operationId: createMyTokenObtainPair
      description: ''
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MyTokenObtainPair'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/MyTokenObtainPair'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/MyTokenObtainPair'
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MyTokenObtainPair'
          description: ''
      tags:
      - api

However, the return type of the function should be TokenRefresh and not MyTokenObtainPair (At least as far as I understand):

  /api/token/:
    post:
      operationId: createMyTokenObtainPair
      description: ''
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MyTokenObtainPair'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/MyTokenObtainPair'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/MyTokenObtainPair'
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenRefresh'
          description: ''
      tags:
      - api

This is unfortunate, as ideally, it would be great if it is possible to autogenerate client code from the generated schema.

Installed python packages: ``` Django==4.1.4 psycopg2-binary==2.9.5 djangorestframework==3.14.0 django-cors-headers==3.13.0 djangorestframework-simplejwt==5.2.2 PyJWT==2.6.0 markdown==3.4.1 django-filter==22.1 pyyaml==6.0 uritemplate==4.1.1 ``` ``` python -m jwt.help { "cryptography": { "version": "" }, "implementation": { "name": "CPython", "version": "3.11.1" }, "platform": { "release": "6.1.1-arch1-1", "system": "Linux" }, "pyjwt": { "version": "2.6.0" } } ``` Django settings.py: ``` import os from pathlib import Path from datetime import timedelta # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = "" # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ "api", "food", "sugar", "weight", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "rest_framework", "rest_framework_simplejwt.token_blacklist", "corsheaders", "django_filters", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "corsheaders.middleware.CorsMiddleware", ] ROOT_URLCONF = "datahub.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ] WSGI_APPLICATION = "" # Database # https://docs.djangoproject.com/en/4.0/ref/settings/#databases POSTGRES_PORT = int(os.environ.get("POSTGRES_PORT", "5432")) POSTGRES_HOST = os.environ["POSTGRES_HOST"] POSTGRES_DB = os.environ["POSTGRES_DB"] POSTGRES_USER = os.environ["POSTGRES_USER"] POSTGRES_PASSWORD = os.environ["POSTGRES_PASSWORD"] DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "HOST": POSTGRES_HOST, "NAME": POSTGRES_DB, "PASSWORD": POSTGRES_PASSWORD, "PORT": POSTGRES_PORT, "USER": POSTGRES_USER, } } # Password validation # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] # Internationalization # https://docs.djangoproject.com/en/4.0/topics/i18n/ LANGUAGE_CODE = "en-us" TIME_ZONE = "UTC" USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ STATIC_URL = "static/" # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ( "rest_framework_simplejwt.authentication.JWTAuthentication", ), "DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"], } SIMPLE_JWT = { "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), "REFRESH_TOKEN_LIFETIME": timedelta(days=50), "ROTATE_REFRESH_TOKENS": True, "BLACKLIST_AFTER_ROTATION": True, "UPDATE_LAST_LOGIN": False, "ALGORITHM": "HS256", "VERIFYING_KEY": None, "AUDIENCE": None, "ISSUER": None, "JWK_URL": None, "LEEWAY": 0, "AUTH_HEADER_TYPES": ("Bearer",), "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", "USER_ID_FIELD": "id", "USER_ID_CLAIM": "user_id", "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule", "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",), "TOKEN_TYPE_CLAIM": "token_type", "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser", "JTI_CLAIM": "jti", "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp", "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5), "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1), } CORS_ALLOW_ALL_ORIGINS = True ```
rbuffat commented 1 year ago

Ups, I just noticed this issue is for the wrong project. Apologies if I caused any inconveniences.