Skip to content
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

Question: How to proxy cookie header from Centrifugo to Django? #214

Closed
xdexer opened this issue Jan 24, 2023 · 6 comments
Closed

Question: How to proxy cookie header from Centrifugo to Django? #214

xdexer opened this issue Jan 24, 2023 · 6 comments

Comments

@xdexer
Copy link

xdexer commented Jan 24, 2023

Hi, we have an Uni diploma project that uses Centrifugo application to build a chat. We are now struggling with authorizing a user, when connecting from React built frontend.

We are using nginx configuration:
nginx.conf

events {
    worker_connections 1024;
}

error_log /dev/stdout info;

http {
    access_log /dev/stdout;

    server {
        listen 80;
        listen [::]:80;

        server_name localhost;
        location / {
            root /usr/share/nginx/html/;
            try_files $uri $uri/ /index.html;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;            
        }
 
        location /backend {
            proxy_pass http://host.docker.internal:8000;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        location /connection/websocket {
            proxy_pass http://host.docker.internal:8001;
            proxy_http_version 1.1;
            proxy_buffering off;
            keepalive_timeout 65;
            proxy_read_timeout 60s;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_cache_bypass $http_upgrade;
        }
    }
}

mainPage.js - when we log in user with Django JWT backend

    useEffect(() => {
        console.log('USE EFFECT CENTIRFGO')
        centrifuge = new CentrifugoService(new Centrifuge("ws://" + "127.0.0.1" + config.CENTRIFUGO_URL, 
        {
            debug: true
        })) 
        centrifuge.getChatRooms()
            .then(data => {
                console.log(data)
            })
    }, [])

Session works and every call directly to backend implements Authorization request header passed with it, where the JWT token is held.

When we try to accomplish this through centrifuge-js service, we cannot pass this header. I assume it is due to websocket protocol switch.

In tutorial there is a mention about "Replace tutorial-user used here with native Django session framework. We already proxying the Cookie header to Django from Centrifugo, so you can reuse native Django authentication. Only allow authenticated users to join rooms."

We are using django-backends:
'django.contrib.sessions'
'rest_framework_simplejwt.authentication.JWTAuthentication'
'django.contrib.sessions.middleware.SessionMiddleware'

centrifugo-viewset.py

from rest_framework.permissions import IsAuthenticated

class CentrifugoViewSet(viewsets.ViewSet):
    permission_classes = [IsAuthenticated]

    @csrf_exempt
    @action(detail=False, methods=['post'])
    def connect(self, request):
            response = {
                'result': {
                    'user': f'{request.user.pk}'
                }
        return JsonResponse(response)

We tried to implement it in a browser cookie, although without success.
Zrzut ekranu 2023-01-24 o 23 47 26

Django receives the request from Centrifugo:
2023-01-24 23:27:52 [24/Jan/2023 22:27:52] "GET /backend/chat/chatroom/ HTTP/1.1" 401 183
2023-01-24 23:27:52 Unauthorized: /backend/chat/centrifugo/connect/

Could you please help us with this issue? How to pass the JWT token to Django to make it validated? We appreciate any support, as we are struggling for a really long time...

@FZambia
Copy link
Member

FZambia commented Jan 25, 2023

Hello @xdexer

Right, Authorization header can't be passed from web browser for WebSocket connection Upgrade HTTP request since browsers do not provide a way to set custom WebSocket Upgrade headers. Cookie header is automatically passed by browser for the domain though.

First thing is to make sure that in Centrifugo configuration you have:

"proxy_http_headers": [
        "Cookie"
]

If it's already set, then check whether Cookie header reaches your backend or not (it should) – maybe just printing all the headers coming to your CentrifugoViewSet connect method (maybe you will need to temporary remove permission_classes = [IsAuthenticated] so that connect method had a chance to be called). If the header is there – I suppose sth wrong with your authentication middleware. If the header is missing – probably it's sth with Centrifugo - then please report the version of Centrifugo server you are using.

Also, I have not worked with Django many years. Make sure your connect handler of class CentrifugoViewSet(viewsets.ViewSet) is really called upon request from Centrifugo. I am not sure viewsets.ViewSet has sth like connect to override.

@FZambia
Copy link
Member

FZambia commented Jan 31, 2023

@xdexer hello - any updates on this?

@xdexer
Copy link
Author

xdexer commented Jan 31, 2023

Hello, thanks for such a quick response, wasn't expecting it! The issue is not related to Centrifugo as it passed the Cookie flawlessly.

The issue turned out to be in the simple-JWT Django library which only expects the JWT in Authorization header. The issue still wasn't resolved: jazzband/djangorestframework-simplejwt#71

The solution is to apply a workaround from the github issue mentioned or switch to the django JWT library (not the simple one). Thank you for getting us onto the right track and solving the issue, and hoping this thread will become useful for others with similar issues.

Best regards and keep up the good work with Centrifugo! :)

@FZambia
Copy link
Member

FZambia commented Jan 31, 2023

Awesome, many thanks! Closing then :)

@FZambia FZambia closed this as completed Jan 31, 2023
@xdexer
Copy link
Author

xdexer commented Mar 19, 2023

Hi @FZambia, I am now writing the diploma paper about the project and would like to include the analysis of integrating auth module with Centrifugo. You helped us a lot by pointing us at the authentication middleware and would like to include your participation in the honorable mentions of the diploma work. What do you think about it? May I reference you in the work? :)

@FZambia
Copy link
Member

FZambia commented Mar 19, 2023

@xdexer hello, yep - feel free, my linkedin profile if required. And good luck with the diploma!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants