asinkxcoswt
asinkxcoswt

Reputation: 2544

Spring get actual scheme from reverse proxy

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;
    }
}

Upvotes: 1

Views: 2385

Answers (1)

miknik
miknik

Reputation: 5941

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...

Upvotes: 3

Related Questions