flask application using flask_oidc with nginx reverse proxy in docker deployed on EC2 giving Not authorized error after authentication with keycloak - nginx

I have the following setup:
1: Keycloak docker container running on an EC2 instance. (I have configured it temporarily to accept http connections)
2: My Flask applicatioĊ„ together with nginx reverse proxy running in docker on another EC2 instance.
I have created the realm and client on keycloak and configured the redirect uri.
I am able to get my flask application to reach the Keycloak instance for authentication.
I added from werkzeug.middleware.proxy_fix import ProxyFix and app.wsgi_app = ProxyFix(app.wsgi_app)to get the redirect_uri to work.
However, when the redirection happens, I get a 'Not authorized' error (i can also see 401 in nginx log).
I have set the OVERWRITE_REDIRECT_URI as OVERWRITE_REDIRECT_URI = 'https://authenticationdemo.mydomain/oidc_callback'
I configured nginx to forward the https request with endpoint oidc_callback to my flask application route /oidc_callback (i do not implement my own callback).
location /oidc_callback{
proxy_pass http:/<flask_app_name_in_docker>:<port>/oidc_callback;
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_set_header X-Forwarded-Host $host;
proxy_redirect off;
}
I am not able to solve this problem as I am not able to figure our where the callback is going wrong. I can see the log from nginx with GET /oidc_callback?state=<...somevalue..>&session_state=<...somevalue>&code=<..somevalue...>
But after redirection this does not work.
I tried both by
using ip addresses in the redirect uri
domain name same as my certificates and configuring hosts file on the EC2 instance with keycloak to point to the correct ip address of the EC2 instance with flask application
Both are not working.
I am not able to figure out if something is going wrong in passing back the authentication information or is there some basic config wrong.
Can somebody please point to the correct approach?
I already looked up and tried information in other related questions:
Flask_oidc gives Errno 99 Cannot assign requested address when run in Docker container
flask-oidc-redirect-uri-value-being-overwritten-somewhere
flask-oidc-with-keycloak-oidc-callback-default-callback-not-working
(and read many other similar ones)
I am not looking for a custom callback. I just need the default callback behavior as it is without a reverse proxy.

Update:
I figured out that the problem was due to the failing check for matching 'OIDC_VALID_ISSUER' in the function _is_id_token_valid(self,id_token) in flask_oidc. Putting port number in the url for issuer in client_secrets was causing the problem. Removing it solved the problem.

Related

nginx proxy pass ip from url

I have multiple web servers with IP address say 172.18.1.1 to 172.18.1.20, hosting different website on 443(https) and A nginx server which I need to use for proxying above servers.
Example :
My nginx server IP is https://10.220.5.39:9200 by giving web server in URL , I need to show the websites
i.e. https://10.220.5.39:9200/proxy/172.18.1.1, should get website of https://172.18.1.1
AND
https://10.220.5.39:9200/proxy/172.18.1.2, should get website of https://172.18.1.2
location /proxy/(?<uniqueId>[^/]+).* {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass https://$uniqueId/;
}
But it is not working , I can not use redirect , since client will not have access to web servers directly
Also some website use css file from route i.e. href="/static/theme.css"
because of which in browser console we are getting
not found https://10.220.5.39:9200/static/theme.css
Is this even possible with nginx

Nginx reverse proxy to backend gives an error ERR_CONNECTION_REFUSED

I have an application running on a server at port 6001(frontend, built by react.js) and port 6002(backend, built by node.js) in EC2 instance.
When I send a request through ubuntu terminal in the instance by curl -X GET http://127.0.0.1:6002/api/works, It works fine, I get a proper data.
Now I go to a browser with the domain (http://example.com). However, I only get the front end getting called. When I send a request on a browser to the backend server, It gives me an error GET http://127.0.0.1:6002/api/works net::ERR_CONNECTION_REFUSED (the domain goes through ELB)
Here's my nginx config.
server {
listen 80;
listen [::]:80;
server_name example.com;
root /home/www/my-project/;
index index.html;
location / {
proxy_pass http://127.0.0.1:6001/;
}
location /api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_pass http://127.0.0.1:6002/;
proxy_set_header X-Real-IP $remote_addr;
}
}
my case is similar to this, he/she says
My entry point via the aws dns takes me to the React app 127.0.0.1:4100 that is the port 80 nginx is listening to. The react app is the one that makes the backend calls and it is coded to make the backend api calls on 127.0.0.1:1323/api. The client error you saw was because it is displaying what the react app is trying to call in the server, but nginx is not redirecting that call to the app that is running at that port. Does that make sense?
the selected answer didn't work on me.
Also, According to the comment, the problem is solved by sending a request by http://AWS_IP/ on the react app. but I'm not sure If it's a good solution for me since there's no point to use ELB then? If I understand the concept of ELB right? I think the requests need to be done via ELB?
Please help, this is driving me crazy.
From your question, I understood the following things,
Your Domain is pointing to Amazon ELB
And there is a VM behind this ELB, and it has Nginx and 2 applications in it.
Nginx is listening on port 80 and Backend application is listening on port
6002 and frontend is listening on port 6001
YOUR FRONTEND APPLICATION IS CALLING THE BACKEND FROM YOUR LOCAL BROWSER USING
http://127.0.0.1:6002/api/works
Here is the problem,
You can curl 127.0.0.1 from the same instance where the application is running(listening to port 6001) because you are hitting the localhost of that instance, And it is different when your web application running on your local browser because your react application(all javascript application) executes in your local machine and for backend call, it is hitting the localhost(in your case) and returning CONNECTION REFUSED.
So the solution is you've to change the backend URL so that it should look something like http://yourdomain/api/works
In Addition to this, I've a couple of suggestions on your configuration.
You don't need a separate web server for your frontend since you can use the same Nginx.
Make sure that your ELB target port is 80 or the same port that NGINX is listening to.
And close the ports 6001 and 6002 (if it is publically accessible)

ASP.NET Owin OAuth callback URL with reverse proxy

I need your help to solve an issue i have with OAuth on my MVC5 application. On my development environment everything's fine. I set up Twitter/Google/Facebook/Microsoft providers and it works like a charm for now.
My issue is on a test environment. I'm using nGinx as a front server to holds the certificates and serves some static content through a subdirectory of the domain.
The proxy part is configured as followed :
location / {
proxy_pass http://localhost:8080;
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;
}
The problem is that all my configured callback URLs for external providers are on the HTTPS scheme but running the application on HTTP makes the callback url having an HTTP protocol (for example, the authorized callback URL is https://example.com/signin-facebook but the effective callback URL sent to provider is http://example.com/signin-facebook).
I saw on other posts that there is a AspNetCore solution with UseForwardedHeaders but as i'm still on normal AspNet, it's not an option.
As a dirty workaround, i temporarly allowed URLs with an HTTP protocol as callback URLs for Twitter/Facebook and Google but Microsoft is strict and only allow HTTPS (This workaround works because my nGinx is configured to perform a 301 Redirect on incoming HTTP requests to the same request over HTTPS)
Does anyone have a solution to change the scheme of the base URL used to build the callback URL ?

Dynamic nginx upstream doesn't work with authorization header

I have a problem with a particular nginx setup. The scenario is like this: Applications need to access a couchdb service via a nginx proxy. The nginx needs to set an authorization header in order to get access to the backend. The problem is that the backend service endpoint's DNS changes sometimes and that's causing my services to stop working until I reload nginx.
I'm trying to setup the upstream as a variable, but when I do that, authorization stops working, the backend returns 403. When I just use the upstream directive, it works just fine. The upstream variable has the correct value, no errors in logs.
The config snippet below:
set $backend url.to.backend;
location / {
proxy_pass https://$backend/api;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host url.to.backend;
proxy_set_header Authorization "Basic <authorization_gibberish>";
proxy_temp_path /mnt/nginx_proxy;
}
Any help will be appreciated.
Unless you have the commercial version, nginx caches the resolution of an upstream (proxy_pass is basically a "one server upstream"), so the only way to re-resolve it is to perform a restart or reload of the configuration. This is assuming the changing DNS is the issue.
From the upstream module documentation:
Additionally, the following parameters are available as part of our
commercial subscription:
...
resolve - monitors changes of the IP
addresses that correspond to a domain name of the server, and
automatically modifies the upstream configuration without the need of
restarting nginx (1.5.12)

404s on AWS deployed MEAN app

I have a MEAN.io application deployed to AWS EC2. Its running via Nginx proxy pass on a 8087 port, config is as follows:
location /myapp/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://0.0.0.0:8087/;
}
The problem I have is that in the browser some POST/PUT requests sent via AJAX are returning 404 errors and default nginx error page. Those requests are not even making it through to Node.js server as I can see in the logs that they are not recorder. There is definately a route provided for those requests, as the app works totally fine on localhost. The same POST/PUT requests seem to work fine when queried directly using 'curl' in the console.
I am not an nginx / AWS expert, so I wanted to ask simple question - is there anyway nginx could be caching those requests and why would they return different HTTP code when queried from 'curl' or via AJAX in the browser?
I think you have a problem with the way you have configured your nginx server, please do check the following rules for nginx.
url rewriting
public folder and
static content

Resources