Skip to content

Q&A

JWT auth not working?

Solution

(frontend) app/src/utils/requests.js -> request interceptor set config.headers['Authorization'] = 'Bearer ' + getToken()

service.interceptors.request.use(
...
    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['Authorization'] = 'Bearer ' + getToken()
    }
    return config
  },
...

Backend response format not matching?

Solution

(backend) Change your response_model schemas in app/app/api/schemas

(frontend) app/src/utils/requests.js -> response interceptor set const res = {...}

service.interceptors.response.use(
...
response => {
    const hasData = response.data != null
    const hasDetail = hasData ? response.data.detail != null : false
    const res = {
    'code': response.status,
    'data': hasData ? response.data : null,
    'message': hasDetail ? response.data.detail : null
    }
...

(backend) app/app/main.py -> add middleware to handle response

# it formatted response, but openapi crashed
import json

class async_iterator_wrapper:
    def __init__(self, obj):
        self._it = iter(obj)
    def __aiter__(self):
        return self
    async def __anext__(self):
        try:
            value = next(self._it)
        except StopIteration:
            raise StopAsyncIteration
        return value

@app.middleware("http")
async def format_output_for_frontend(request: Request, call_next):
    response = await call_next(request)

    res_body = [x async for x in response.__dict__['body_iterator']]

    try:
        if 200 <= response.status_code < 300:
            status = True
        else:
            status = False

        res_body_json = res_body[0]
        res_body_data = json.loads(res_body_json)
        if res_body_data is not None:
            msg = res_body_data.pop('detail', None)
            data = dict(res_body_data)
        else:
            msg = None
            data = None

        res_body_data = {
            'status': status,
            'msg': msg,
            'data': data,
        }
        res_body_json = json.dumps(res_body_data)
        res_body = [res_body_json.encode()]
        response.headers['content-length'] = str(len(res_body_json))
    except:
        pass

    response.__setattr__('body_iterator', async_iterator_wrapper(res_body))

    return response

Cookie is not stored?

Solution

(backend) Ensure cookie body is not larger than 4kb, otherwise use sessionStorage instead at app/src/utils/auth.js

export function getToken() {
return sessionStorage.getItem(TokenKey)
}

export function setToken(token) {
return sessionStorage.setItem(TokenKey, token)
}

export function removeToken() {
return sessionStorage.removeItem(TokenKey)
}

Check your host, port configs in traefik, frontend, backend

  1. (backend) Enable CORSMiddleware at app/app/main.py
    # to enable Access-Control-Allow-Credentials
    # to enable Access-Control-Allow-Origin for frontend origin
    # P.S. Origin is only considered to be the same if the protocol, host and port is the same
    # Ref. https://www.w3.org/Security/wiki/Same_Origin_Policy
    app.add_middleware(
        CORSMiddleware,
        allow_origins=[
            'http://localhost:9528',
            'http://127.0.0.1:9528'
            ],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    
  2. (frontend) Enable axios withCredentials at app/src/utils/request.js
    const service = axios.create({
        baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
        withCredentials: true, // send cookies when cross-domain requests
        timeout: 5000 // request timeout
        })
    
  1. (frontend) app/src/utils/auth.js -> set const TokenKey = 'fastapiusersauth'
  2. (fastapi-users) set CookieAuthentication(..., cookie_samesite='None')
Back to top