2

I have a Play! framework Heroku project that has three deployments. One for running my dev machine, one for beta on Heroku, and one for production on Heroku. Their http and https urls are as follows:

             DEV                     BETA                                 PRODUCTION    
HTTP URL   | http://localhost:9000   http://domain-beta.herokuapps.com    http://www.domain.com
HTTPS URL  | https://localhost:9443  https://domain-beta.herokuapps.com   https://secure.domain.com
HTTPS Type | My cert                 Piggyback (using Heroku's cert)      Hostname-based SSL (using my cert)

I also have a class HttpsRequired that has methods for requiring HTTPS, and for redirecting back to HTTP (thanks to this post for the help).

public class HttpsRequired extends Controller {
    /** Called before every request to ensure that HTTPS is used. */
    @Before
    public static void redirectToHttps() {
        //if it's not secure, but Heroku has already done the SSL processing then it might actually be secure after all
        if (!request.secure && request.headers.get("x-forwarded-proto") != null) {
            request.secure = request.headers.get("x-forwarded-proto").values.contains("https");
        }

        //redirect if it's not secure
        if (!request.secure) {
            String url = redirectHostHttps() + request.url;
            System.out.println("Redirecting to secure: " + url);
            redirect(url);
        }
    }

    /** Renames the host to be https://, handles both Heroku and local testing. */
    @Util
    public static String redirectHostHttps() {
        if (Play.id.equals("dev")) {
            String[] pieces = request.host.split(":");
            String httpsPort = (String) Play.configuration.get("https.port");
            return "https://" + pieces[0] + ":" + httpsPort; 
        } else {
            if (request.host.endsWith("domain.com")) {
                return "https://secure.domain.com";
            } else {
                return "https://" + request.host;
            }
        }
    }

    /** Renames the host to be https://, handles both Heroku and local testing. */
    @Util
    public static String redirectHostNotHttps() {
        if (Play.id.equals("dev")) {
            String[] pieces = request.host.split(":");
            String httpPort = (String) Play.configuration.get("http.port");
            return "http://" + pieces[0] + ":" + httpPort;
        } else {
            if (request.host.endsWith("domain.com")) {
                return "http://www.domain.com";
            } else {
                return "http://" + request.host;
            }
        }
    }
}

I modified Secure.login() to call HttpsRequired.redirectToHttps() before it runs, to ensure that all passwords are submitted encrypted. Then, in my Security.onAuthenticated(), I redirect to the homepage on standard HTTP.

This works great on my dev and beta deployments, but in production all of my HTTP requests are redirected to the HTTPS login page. I can still use the whole site in HTTPS, but I want regular HTTP to work too.

All of my pages are protected as members-only and require users to login, using the @With(Secure.class) annotation. I'm thinking that it must be related to the fact that the login happens at secure.domain.com instead of www.domain.com, and that they somehow generate different cookies.

Is there a way to change the login cookie created at secure.domain.com to make it work at www.domain.com?

Community
  • 1
  • 1
Ned Twigg
  • 2,159
  • 2
  • 22
  • 38

1 Answers1

3

Check out the documentation for the setting for default cookie domain.

http://www.playframework.org/documentation/1.2.4/configuration#application.defaultCookieDomain

It explains how you can set a cookie to work across all subdomains.

application.defaultCookieDomain

Enables session/cookie sharing between subdomains. For example, to make cookies valid for all domains ending with ‘.example.com’, e.g. foo.example.com and bar.example.com:

application.defaultCookieDomain=.example.com

Codemwnci
  • 54,176
  • 10
  • 96
  • 129
  • Hmm. This fixed my problem for login cookies, but now I'm having a new problem with validation.keep() not working over HTTPS on Heroku. Made a new question [here](http://stackoverflow.com/questions/9166129/play-framework-on-heroku-validation-keep-isnt-working-over-https). – Ned Twigg Feb 06 '12 at 19:41