I have a Spring Boot Web application running on Widlfly server. I implemented Facebook OAuth login by generate a button "Login With Facebook" linked to Facebook login endpoint.
https://www.facebook.com/v2.5/dialog/oauth?client_id=****&response_type=code&redirect_uri=http://example.com/login/facebook
I generate the value of redirect_uri using following java code.
public static String getFacebookRedirectUrl() {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
if (attrs instanceof ServletRequestAttributes) {
HttpServletRequest request = ((ServletRequestAttributes) attrs).getRequest();
return request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort()
+ request.getContextPath()
+ "/login/facebook";
} else {
throw new RuntimeException("Cannot determine facebook oauth redirect url");
}
}
My website is deployed internally to http://my-ip-address:8080 and have a reversed proxy (nginx) forwarding requests from https://example.com to http://my-ip-address:8080.
The problem is the redirect-uri is always generated as http://example.com/login/facebook instead of https://example.com/login/facebook (not https).
Please help suggest how make request.getScheme() returns https correctly when the user access the website via https. Following is the reverse proxy configuration /etc/nginx/sites-enalbed/mysite.com
server {
listen 80;
listen 443;
server_name example.com www.example.com;
ssl on;
ssl_certificate /etc/nginx/cert.crt;
ssl_certificate_key /etc/nginx/cert.key;
location / {
proxy_pass http://my-ip-address: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;
}
}
request.getScheme() will always be http because you are proxying via http, but you are passing the request scheme in a header, so use that.
Change return request.getScheme() + "://" to return request.getHeader('X-Forwarded-Proto') + "://"
Not sure how java interprets headers, so X-Forwarded-Proto might become X_Forwarded_Proto or xForwardedProto or something else, but you get the idea...
Related
We encountered a very weird behavior when using Nginx as a reverse proxy.
We have REST services that need to be used with the browser, We configured these HTTP Golang services to handle CORS using cors package.
We noticed that when the browser triggers a preflight request the request doesn't go to the backend service and instead Nginx responds with the status 405 Method Not Allowed and the request is never forwarded or proxied to the backend service at all.
To fix this issue we had to handle OPTIONS requests manually from the location directive, This is very limited as we need the liberty to update for example the allowed headers using Access-Control-Allow-Headers based on the requested route.
How can we forward any Preflight or OPTIONS request to the backend to handle?
NOTE: We are using default Nginx configurations according to the official Nginx docker image.
file: main.go
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
})
r := cors.AllowAll().Handler(mux)
http.ListenAndServe(":3000", r)
}
file: server.conf
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
# Handling OPTIONS for this location directive.
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "$http_origin";
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Headers 'Authorization, Content-Type, Origin, X-Requested-With, Accept';
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
add_header Content-Type 'text/plain; charset=utf-8';
return 204;
}
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-Remote-Addr $remote_addr;
proxy_set_header X-Original-Host $host;
}
}
Related:
Handling OPTIONS request in nginx
Cross Origin preflight request in Nginx Proxy
I am currently building my first full-stack application with Vue.js and Python Flask. When I run the frontend and backend separately, I am able to successfully make $.ajax POST requests to my Flask app. However, I am now moving to deploy and am opting to use Dockerfile and nginx. The app works just fine, except when I make the same $.ajax POST I get the error in the console:
POST http://localhost:8007/postimage 502 (Bad Gateway)
Here is the $.ajax call:
const path = '/postimage'
$.ajax({
url: path,
type: 'POST',
data: imageData,
cache: false,
contentType: false,
processData: false
})
.done(function (data) { alert(data + 'success') })
.fail(function (errorMsg) { alert(errorMsg + 'error') })
And here is my nginx default.conf file:
server {
listen $PORT;
root /usr/share/nginx/html;
index index.html index.html;
location / {
try_files $uri /index.html =404;
}
location /ping {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_redirect default;
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-Host $server_name;
}
location /postimage {
proxy_pass http://0.0.0.0:5000;
proxy_http_version 1.1;
proxy_redirect default;
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-Host $server_name;
}
}
NOTE: For the proxy_pass I have tried http://127.0.0.1:5000, http://0.0.0.0:5000, as well as http://localhost:5000 but they all give the same error message.
I am trying to separate my Spring Boot application from my front-end, namely my Angular 7+ application, by using an NGINX reverse proxy.
My Spring Boot application is of version 2.0.3+.RELEASE and has CSRF protection enabled.
My Security configuration looks like the following:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().and()
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
My nginx.conf looks like this:
events {
worker_connections 768;
}
http {
# Nginx will handle gzip compression of responses from the app server
gzip on;
gzip_proxied any;
gzip_types text/plain application/json;
gzip_min_length 1000;
server {
listen 80;
# Nginx will reject anything not matching /api
location /api {
# Reject requests with unsupported HTTP method
if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE)$) {
return 405;
}
# Only requests matching the whitelist expectations will
# get sent to the application server
proxy_pass http://app:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
}
location / {
root /var/www/ui;
try_files $uri $uri/ /index.html =404;
index index.html index.htm;
}
}
}
Considering the following Request Header for http://localhost/api/myResource I get a Forbidden message on POST request:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: it,it-IT;q=0.9,en;q=0.8,it-CH;q=0.7
authorization: Basic
Connection: keep-alive
Content-Length: 94
Content-Type: application/json
Cookie: SESSION=MTdmNGFmODctMTNiMC00YzRjLWJjNTAtYmVlMTgzMzJkZTli; XSRF-TOKEN=fbe30e1e-1f64-4910-9040-799217c59b51
Host: localhost
Origin: http://localhost
Referer: http://localhost/admin/bundles
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
X-Requested-With: XMLHttpRequest
The Spring application logs the following error:
Invalid CSRF token found for http://localhost/api/myResource
NON GET calls should pass in X-XSRF-Token in header when calling backend spring boot server to this explicity ,
#Injectable()
export class CustomInterceptor implements HttpInterceptor {
constructor(private http: Http,private tokenExtractor: HttpXsrfTokenExtractor) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headerName = 'X-XSRF-TOKEN';
let token = this.tokenExtractor.getToken() as string;
console.log(token)
if (token !== null && !request.headers.has(headerName)) {
request = request.clone({ headers: request.headers.set(headerName, token) });
}
Socket.io handshake fails on my site but not on localhost.
I had to provide a custom handshake because socket.io was unable to find my query parameter.
Here is my declaration in socket.service.js:
var ioSocket = io('https://my-site.rhcloud.com//?EIO=2&transport=polling&t=1414328625757-0&
token=' + Auth.getToken(), {
});
and how I catch it on server side :
socketio.use(function(socket, next) {
request.get('https://my-site.rhcloud.com/api/users/chan', {qs:{access_token:socket.handshake.query.token}}, function(err, me) {
if (err||!me.body|| me.body=='Unauthorized') {
if (!me) console.log('!me');
if (err) console.log(err);
next(err);
}
else {
// perfoming operations
next();
}
});
});
Here is the message I get:
WebSocket connection to 'wss://my-site.rhcloud.com/socket.io/?EIO=2&transport=websocket&t=…YwMX0.1F6ebfNxzoDPYffXGapGMzLFPJd-mfN0EexqZzXXo7A&sid=z0Jmrbgb7OS0nbqxAAAG' failed: Error during WebSocket handshake: Unexpected response code: 400
I'm really lost here, and digged a lot into Google without any success.
Any help would be really appreciated !
After a lot of search, I realized the problem came from Openshift. You have to specify the port sockets are going to use. See this article: https://blog.openshift.com/paas-websockets/
So, I just had to write:
var ioSocket = io('http://my-site.rhcloud.com:8000, {
});
Nginx proxy solves the issue with the following config:
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
Original solution here. It works great for me (Ubuntu 14.4 + Plesk 12.5).
I deployed my node/express server to Azure and I got the folowing error
websocket.js:100 WebSocket connection to 'ws://mywebsitename.azurewebsites.net/socket.io/?EIO=3&transport=websocket&sid=ssEHs-OWxI6mcChyAAAB' failed: Error during WebSocket handshake: Unexpected response code: 503
, I fixed my issue by enable WebSocket in Azure console as shown below
I've got a proxy running that only hits my node.js server for paths that being with /mysubdir
How do I get socket.io configured for this situation?
In my client code I tried:
var socket = io.connect('http://www.example.com/mysubdir');
but then I notice that the underlying socket.io (or engine.io) http requests are hitting
http://www.example.com/socket.io/?EIO=3&transport=polling&t=1410972713498-72`
I want them to hit
http://www.example.com/mysubdir/socket.io.....
Is there something I have to configure on the client and the server?
In my server I had to
var io = require('socket.io')(httpServer, {path: '/mysubdir/socket.io'})`
In my client I had to
<script src="http://www.example.com/mysubdir/socket.io/socket.io.js"></script>
and also
var socket = io.connect('http://www.example.com', {path: "/mysubdir/socket.io"});`
In my case I am using nginx as a reverse proxy. I was getting 404 errors when polling. This was the solution for me.
The url to the node server is https://example.com/subdir/
In the app.js I instantiated the io server with
var io = require('socket.io')(http, {path: '/subdir/socket.io'});
In the html I used
socket = io.connect('https://example.com/subdir/', {
path: "/subdir"
});
Cheers,
Luke.
Using nginx, this a solution without the need to change anything in the socket.io server app:
In the nginx conf:
location /mysubdir {
rewrite ^/mysubdir/(.*) /socket.io/$1 break;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.1.1:3000;
}
In the server:
var io = require('socket.io')(3000)
In the client:
var socket = io.connect('https://example.com/', {
path: "/mysubdir"
})
The answer by #Drew-LeSueur is correct for socket.io >= 1.0.
As I was using socket.io 0.9, I found the old way of doing it in the doc.
// in 0.9
var socket = io.connect('localhost:3000', {
'resource': 'path/to/socket.io';
});
// in 1.0
var socket = io.connect('localhost:3000', {
'path': '/path/to/socket.io';
});
Notice that a / appears as first character in the new path option.