New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Websocket Support #14
Comments
Possible solution would be to add a function that just validates the JWT and CSRF (if it's enabled) that can be imported so that I can use it in my websocket routes. |
Here's the function I'm currently trying to get this to work on: @router.websocket("/stats")
async def dashboard(websocket: WebSocket):
auth_success = await websocket_auth(websocket=websocket)
if auth_success:
await websocket.accept()
tasks = []
async with aiodocker.Docker() as docker:
containers = []
_containers = await docker.containers.list()
for _app in _containers:
if _app._container["State"] == "running":
containers.append(_app)
for app in containers:
_name = app._container["Names"][0][1:]
container: DockerContainer = await docker.containers.get(_name)
stats = container.stats(stream=True)
tasks.append(process_container(_name, stats, websocket))
await asyncio.gather(*tasks)
else:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
async def process_container(name, stats, websocket):
cpu_total = 0.0
cpu_system = 0.0
cpu_percent = 0.0
async for line in stats:
if line["memory_stats"]:
mem_current = line["memory_stats"]["usage"]
mem_total = line["memory_stats"]["limit"]
mem_percent = (mem_current / mem_total) * 100.0
else:
mem_current = None
mem_total = None
mem_percent = None
try:
cpu_percent, cpu_system, cpu_total = await calculate_cpu_percent2(
line, cpu_total, cpu_system
)
except KeyError as e:
print("error while getting new CPU stats: %r, falling back")
cpu_percent = await calculate_cpu_percent(line)
full_stats = {
"name": name,
"cpu_percent": cpu_percent,
"mem_current": mem_current,
"mem_total": mem_total,
"mem_percent": mem_percent,
}
try:
await websocket.send_text(json.dumps(full_stats))
except Exception as e:
pass
async def websocket_auth(websocket: WebSocket):
try:
cookie = websocket._cookies["fastapiusersauth"]
user = await cookie_authentication(cookie, user_db)
if user and user.is_active:
return user
elif settings.DISABLE_AUTH == "True":
return True
except:
if settings.DISABLE_AUTH == "True":
return True
else:
return None (Just wanted to add an example of what manual validation could look like) |
Hi @SelfhostedPro, I know the problem it is, fastapi-jwt-auth extract data which is cookies or headers from request instead from WebSocket, I will fix this in the next version thanks 🙏 |
Glad to hear it! Super excited to be using this in my project. |
Hi @SelfhostedPro you can get a new version for support WebSocket, also you can check the documentation here, if you have any question or suggestion please let me now 😁 , or if this version enough for you, you can close this issue thankyou 🙏 |
I'll try it out today and let you know how it goes. Thanks! |
I'm currently getting the following error in my websocket functions. Seems like it doesn't like me specifying the token argument for some reason.
This is the function in question: @router.websocket("/{app_name}/livelogs")
async def logs(websocket: WebSocket, app_name: str, Authorize: AuthJWT = Depends()):
try:
csrf = websocket._cookies["csrf_access_token"]
Authorize.jwt_required("websocket", token=csrf)
except AuthJWTException as err:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
await websocket.accept()
async with aiodocker.Docker() as docker:
container: DockerContainer = await docker.containers.get(app_name)
if container._container["State"]["Status"] == "running":
stats = container.stats(stream=True)
logs = container.log(stdout=True, stderr=True, follow=True)
async for line in logs:
try:
await websocket.send_text(line)
except Exception as e:
return e
else:
await websocket.close(code=status.WS_1011_INTERNAL_ERROR) Here's the full error:
|
btw if you want to authorization with cookies you must be passing WebSocket instance to try:
csrf = websocket._cookies["csrf_access_token"]
Authorize.jwt_required("websocket", websocket=websocket, token=csrf) # like this
except AuthJWTException: # delete as err if you no need that message
await websocket.close(code=status.WS_1008_POLICY_VIOLATION) |
Changed over to that as well with no luck. Getting the following error: @router.websocket("/{app_name}/livelogs")
async def logs(websocket: WebSocket, app_name: str, Authorize: AuthJWT = Depends()):
try:
csrf = websocket._cookies["csrf_access_token"]
Authorize.jwt_required("websocket",websocket=websocket,csrf_token=csrf)
except AuthJWTException:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
await websocket.accept()
async with aiodocker.Docker() as docker:
container: DockerContainer = await docker.containers.get(app_name)
if container._container["State"]["Status"] == "running":
stats = container.stats(stream=True)
logs = container.log(stdout=True, stderr=True, follow=True)
async for line in logs:
try:
await websocket.send_text(line)
except Exception as e:
return e
else:
await websocket.close(code=status.WS_1011_INTERNAL_ERROR) This is to show I'm on the latest version: [user@user-desktop Yacht]$ pip show fastapi-jwt-auth
Name: fastapi-jwt-auth
Version: 0.5.0
Summary: FastAPI extension that provides JWT Auth support (secure, easy to use and lightweight)
Home-page: https://github.com/IndominusByte/fastapi-jwt-auth
Author: Nyoman Pradipta Dewantara
Author-email: nyomanpradipta120@gmail.com
License: UNKNOWN
Location: /home/user/dev/Yacht-work/Yacht/backend/venv/lib/python3.8/site-packages
Requires: fastapi, PyJWT
Required-by: |
Here is the source code for that section of my app if you wanted to know that as well: |
Can you try a fresh install? its doesn't make sense my package doesn't have websocket or token argument its like your application use my previous version which is doesn't have that all argument |
Deleted my project, cloned, setup a new venv, and installed with --no-cache-dir and still getting the same error. Is it possible pypi doesn't have the correct files in the new version? |
Checked on pypi and in my venv and it looks like it's the correct version. |
Also tried just doing positional arguments with no luck.
@router.websocket("/stats")
async def dashboard(websocket: WebSocket, Authorize: AuthJWT = Depends()):
try:
csrf = websocket._cookies["csrf_access_token"]
Authorize.jwt_required("websocket",None,websocket,csrf)
except AuthJWTException:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
await websocket.accept()
tasks = []
async with aiodocker.Docker() as docker:
containers = []
_containers = await docker.containers.list()
for _app in _containers:
if _app._container["State"] == "running":
containers.append(_app)
for app in containers:
_name = app._container["Names"][0][1:]
container: DockerContainer = await docker.containers.get(_name)
stats = container.stats(stream=True)
tasks.append(process_container(_name, stats, websocket))
await asyncio.gather(*tasks) |
If you'd be willing to try out my project and see here are the instructions: backend:
frontend(in another terminal):
If you use vscode, this is the launch.json I use for debugging:
|
Okay, I will try to run your application |
Have a friend who's using the same example as in your documentation and is getting the same error. Nothing is popping out to me as far as where the issue is in fastapi-jwt-auth though. |
Are you using a virtual environment? I've never run into something like this before so I'm not really sure where to go from here as far as troubleshooting. I'll try re-imaging my machine after work today and see if that changes anything. |
I testing it on docker because you provide Dockerfile, and I don't get an error message as you get. and I try to different machine and work to |
Use the virtual environment in a different machine is working well to |
I can confirm it's working within docker. Thanks! |
Great! glad to hear that 😁 🙏 |
I assume the original issue was resolved. But feel free to add more comments or create new issues 😄 🙏 |
* Update python version in tests to 3.10
Currently it looks as though websockets wont work with the standard require_jwt_auth() even when sent via cookies (which works with flask_jwt_extended). This is the error I'm getting:
The text was updated successfully, but these errors were encountered: