a bit confused about the process here:
i have a keycloak container that once i login gives me something like this:
http://10.357.35.22/mainpage/?session_state=604471e5-6ecc-454e-9839-ef57a1b4d767&code=9e59150c-8944-42c5-9590-ac1184af8e68.604471e5-6ecc-454e-9839-ef57a1b4d767.2d2b79fc-8cdc-4ed0-8ca6-1031d256a020
i have no idea what to do with this in the mainpage location:
location /mainpage/ {
alias /usr/share/nginx/html;
index index.html;
}
how would i go about check whatever headers against a secret i have.
here is the authentication location:
location / {
proxy_pass http://10.357.35.22:5555/keys/realms/my_realm/protocol/openid-connect/auth?response_type=code&client_id=landing_page&redirect_uri=http://10.357.35.22:5555/mainpage/
# allow the CROS requests
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Sinc>
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
i'm just trying to put up a login screen in front of an app...so i've spent a long time trying to get to here, but i'm honestly stuck. i could request for a token, but again, not sure how to use it in nginx.
nginx and keycloak are both in docker containers.
Related
I want to handle cors on nginx unit level but I don't know how it make on nginx unit.
Example config for nginx
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, OPTIONS, DELETE, PATCH';
add_header 'Access-Control-Allow-Headers' 'Authorization,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range';
add_header 'Access-Control-Expose-Headers' 'Gc-Export-Errors';
return 204;
}
How I can do this for nginx unit?
Currently, Nginx Unit doesn't support functionality equal to add_header so if you need custom headers for 204 response it should be done using application. And configuration will looks like this:
{
"match":{
"method": "OPTIONS"
},
"action":{
"proxy": "path/to/app_return_204_with_custom_headers"
}
}
I am developing a nginx server to work as a reverse proxy to a local webapp only when user is authenticated.
Here is my nginx myconfiguration.conf flie inside etc/nginx/sites-enabled/:
# Proxy Server to back-end site
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name internal.example.com;
# Internal web application
location / {
auth_request /aut;
error_page 401 = #error401;
proxy_pass http://192.168.1.13:8080;
}
# Autentication application
location = /aut {
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass http://192.168.1.130:8080/Autentication/Auth;
}
# Redirect to login site
location #error401 {
return 302 http://example.com/Autentication/login;
}
}
# Proxy server to Login site
server {
listen 80;
listen [::]:80;
server_name example.com;
# Internal web application for login
location / {
proxy_pass http://192.168.1.130:8080;
}
}
If users requests are authenticated through the auth_request /aut; everithing works great, but if we force the auth_request (on our auth api) to answer 'HTTP error 401' we slip into 2 different situations:
A) if the user refresh the page, everithing works: it means that the request do not pass the authorization and the client is redirected to our login page http://example.com/Autentication/login
B) if the user tries to fetch data from an api using javascript we receive this 3 errors in the browser console:
ERROR .1)
Access to XMLHttpRequest at 'http://example.com/Autentication'
(redirected from 'http://internal.example.com/TestServer/servlet')
from origin 'http://internal.example.com' has been blocked by CORS policy:
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response
ERROR 2)
Access to XMLHttpRequest at 'http://example.com/Autentication'
(redirected from 'http://internal.example.com/page.html')
from origin 'http://internal.example.com/' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
ERROR 3)
Access to XMLHttpRequest at 'http://example.com/Autentication'
(redirected from 'http://internal.example.com/TestServer/servlets)
from origin 'http://internal.example.com' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
We tried, as suggested here, to add this configurations in our nginx myconfiguration.conf inside the location block but it didn't solved our problem:
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
After few days of testing some change here and there I SOLVED the problem:
No configuration needed on tomcat server (i mean no cors headers handled on tomcat server).
What i changed and was enough to let the whole infrastructure work was the myconfig.conf file on NGINX.
Here is the correct myconfig.conf:
# SERVER PROXY INTERNAL (can access only when auth_request is passed)----------------------------------------
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name internal.example.com;
# Proxy to internal tomcat with auth_request to /provaut
location / {
auth_request /prova_aut;
error_page 401 = #error401;
proxy_pass http://192.168.1.13:8080;
}
location = /prova_aut {
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass http://192.168.1.130:8080/Auth;
}
# Redirect to LOGIN
location #error401 {
return 302 http://example.com/Login;
}
}
# SERVER PROXY FOR LOGIN AND AUTH TOMCAT'S APP --------------------------
server {
listen 80;
listen [::]:80;
server_name example.com;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
# Proxy to Authentication_app's tomcat
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'http://internal.example.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' 'http://internal.example.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Access-Control-Allow-Origin,Access-Control-Allow-Credentials' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' 'http://internal.example.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Access-Control-Allow-Origin,Access-Control-Allow-Credentials' always;
}
proxy_pass http://192.168.1.130:8080;
}
}
What really made the trick was adding the two lines below in the /location block of the Login/Auth server
'Access-Control-Allow-Origin' 'http://internal.example.com' always;
and
'Access-Control-Allow-Credentials' 'true' always;
I Really hope this can help someone else ;)
I use django-cors-headers 3.1.1 for handling the requests and responses between my Django-backend and Javascript-frontend apps. Transport is non-secured (i.e. http, not https).
When hosted locally, everything works fine. But after deploying on the server, I stopped seeing the CORS headers.
Here are headers in development:
and in production:
Error message:
Access to XMLHttpRequest at 'http://[HOST_IP]/api/assets/' from origin 'http://my_custom_domain.eu' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
My nginx configurations looks as follows:
server {
listen 80;
server_name [HOST_IP];
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 86400;
if ($request_method = 'OPTIONS') {
add_header 'Content-Type' 'text/html; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /static/ {
autoindex on;
alias /home/ubuntu/[path_to_app]/site/static/;
}
}
The django-cors-headers’ settings are now identical in development and in production:
INSTALLED_APPS = (
…
"corsheaders",
…
)
MIDDLEWARE = [
…
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
…
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = ['DELETE','GET','OPTIONS','PATCH','POST','PUT']
On the client side I tried to add ‘'Access-Control-Request-Method’: ‘PUT’ header, but this was refused by the browser. There’s noting unusual in the client call:
axios({
method: 'put',
url: `${this.backendUrl}/api/assets/`,
data: formData,
headers: {
'Content-Type': 'application/octet-stream',
}
})
Also, I’m trying to host on the Amazon AWS EC2 for the first time, so perhaps there is some required AWS configuration I am not aware of. For example, is it necessary to enable CORS using the API Gateway? The documentation does not say so (‘If you are using the API Gateway Import API, you can set up CORS support using an OpenAPI file’).
The frontend application is hosted on a S3 bucket with the following CORS policy:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
What am I missing here? Is there some needed server-side (nginx especially) configuration?
Some other solutions I’ve tried:
I have doubts, whether the request/response origin is correct (e.g. APPEND_SLASH variable). But if this is the case, shouldn’t an error be raised when hosted locally?
I also tried setting proxy headers as in this question, but without knowing nginx very well this was doomed to fail.
I managed to solve this issue by changing 3 things:
AWS
I noticed that AWS documentation states:
CORS is already enabled for the Amazon EC2 API, and is ready for you
to use. You do not need to perform any additional configuration steps
to start using this feature. There is no change to the way that you
make calls to the Amazon EC2 API; they must still be signed with valid
AWS credentials to ensure that AWS can authenticate the requestor. […]
This is usually handled by AWS SDK or CLI, but in my case I used none of them, so I had to add AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. In my case I simply used aws4 library:
axios(aws4.sign({
accessKeyId: this.awsAccessKey,
secretAccessKey: this.awsSecretAccessKey,
method: 'put',
url: `${this.backendUrl}/api/assets/`,
data: formData,
body: JSON.stringify(formData),
service: 'ec2',
region: 'eu-central-1',
path: '/',
headers: {
'Content-Type': 'application/octet-stream'
}
}))
I’ve seen plenty of examples how to add AWS Signature v.4 without any additional dependency, though.
NGINX
In nginx configuration I placed all add_headers statements into conditional code-blocks. Idea came from this post.
server {
listen 80;
server_name [HOST_IP];
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/html; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /static/ {
autoindex on;
alias /home/ubuntu/analizy/be/site/static/;
}
}
Django-cors-header
Here it sufficed to add non-default headers.
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = list(default_headers) + [
'X-Amz-Date',
]
Hope that this will help someone.
After a lot of searches and tries, I have decided to post my problems around CORS.
Context
I have a web site on a local server (NGINX), located on a PI. My web site deals with a microservice through REST API.
My PI is behind my Freebox (French internet box), which redirect a specific port (ex : 28800) to the local # of my pi. FYI, I don't have (and don't want) a fixed IP. And I share my IP with others users. So, I have a range of ports between 20000 and 30000 (approximatively).
And I have a NO-IP hostname, pointed on my freebox IP completed with the specifc port.
To resume:
User -> mysite.no-ip.com ---(Translation NO-IP)---> 91.123.456.678:specifcport ---- (Redirect to my pi) ---> 192.168.0.30:80----(nginx)--->index.html
What I can do:
In my nginx site conf, I set a location /core.
When I do
mysite.no-ip.com/core/blabla, I well obtain the blabla treatment.
No problem!!
Here is my problem:
When I click on the button which launches the blabla action (throught an AJAX POST on mysite.no-ip.comm/core/blabla), I get a CORS failure.
I have tried to modify my nginx configuration, adding headers depends of OPTIONS/GET/POST request type. Nothing appends.
But, I find that my nginx is never touched by the request /core/blabla if this one is send by button. I have a CORS answer thrown by an APACHE Server. And I didn't install any APACHE Server. So, perhaps, it's a server hidden in my Freebox? Don't know how to set it to allow CORS request.
Here is a snippet of my nginx config file
server {
listen 80;
server_name mysite.no-ip.com
location / {
alias /path/to/root/production/folder/here;
}
location /core/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
proxy_pass http://localhost:8002/;
}
}
Thank you for your help.
Ok, Fix my problem which was solved by a combination of my Internet provider box configuration and addition of some headers on my request.
The goal is for nginx server to pass a custom request header called X-PA-AUTH_TOKEN to the uwsgi server. Below is the server block in nginx.conf file.
server {
listen 9390 default_server;
server_name _;
location / {
include uwsgi_params;
uwsgi_pass_request_headers on;
uwsgi_pass unix:/run/uwsgi/irm.sock;
uwsgi_pass_header X-PA-AUTH_TOKEN;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-PA-AUTH_TOKEN';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
add_header 'X-PA-AUTH_TOKEN' '0';
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-PA-AUTH_TOKEN';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,X-PA-AUTH_TOKEN';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-PA-AUTH_TOKEN';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,X-PA-AUTH_TOKEN';
}
}
}
The uwsgi server receives the conventional headers like 'Content-Type' just fine from the nginx server.
But, the uwsgi server is still not receiving the custom request header X-PA-AUTH_TOKEN from the nginx server when, for example, a POST request is made.
What am I doing wrong here?
I believe by default nginx marks headers with underscores (X-PA-AUTH_TOKEN) as invalid so they get blocked. You can either enable underscores_in_headers: on; in nginx config (docs here) or simply rename your header to be X-PA-AUTH-TOKEN.
Note however that if you enable underscores_in_headers, what you actually receive on the flask side will be renamed to X-Pa-Auth-Token, so i guess it's better to simply rename the header in the first place and not bother with nginx setting.