Building an WSGI app with Flask with LinkedIn API access. The app runs fine in local dev environment but when put behind Nginx reverse proxy with HTTPS, all redirections and LinkedIn callbacks fails with incorrect URL.
Reason for this is because the WSGI binary is running in its own address, usually 127.0.0.1:8080. Without further knowledge the app only knows about "I'm listening on this address" and therefore redirections, even sent for the client, are built against this address. Client certainly can't reach "127.0.0.1:8080" but they're expecting anything to server.com:443 speaking HTTPS.
Therefore the solution is the following.
Configure nginx.
Along side the proxy_pass derivative, add the following:
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-Scheme $scheme;
proxy_set_header X-Port $server_port;
These lines passes the correct external information to the script.
In Flask, access the corresponding information when building redirections:
if 'HTTP_X_SCHEME' in request.environ:
SCHEME = request.environ['HTTP_X_SCHEME']
if 'X_PORT' in request.environ:
_p = int(request.environ['X_PORT'])
if 'HTTP_HOST' in request.environ:
_h = request.environ['HTTP_HOST']
When building redirections using url_for, care must be taken to set _scheme=SCHEME (i.e. forcing using external HTTPS) and _external=True.