[2.1] SSL

3,980 views
Skip to first unread message

Ben McCann

unread,
Feb 5, 2013, 8:21:55 PM2/5/13
to play-fr...@googlegroups.com
Play added some sort of SSL support recently? Any tips on how to use this or are there some docs for it? I'd like to start a server locally using a fake SSL provided by Play if possible.

Thanks,
Ben

James Roper

unread,
Feb 5, 2013, 9:33:41 PM2/5/13
to play-framework
Yes, we need to document this.  Here's a start:

In dev mode, it's very easy, just:

JAVA_OPTS=-Dhttps.port=9443 play run

Play will generate a private key and self signed certificate, which obviously your browser will balk at with a big red warning.  It will reuse that generated self signed certificate for each subsequent run of Play, so you should only get the browser error once.  Obviously this self signed certificate is probably not what you want in production.  Also important to note is that the self signed certificate generation will only work on JVMs that use the sun security libraries (eg Oracle and OpenJDK, but most notably not IBM J9).  On JVMs that don't use these, you will get a NoClassDefFoundError when it tries to generate the certificate.

In prod (and this config also applies to dev) you configure it much the same way that you configure SSL ordinarily in Java, via system properties.  Here's a summary:

https.port - The port that should be used
https.keyStore - The path to the keystore containing the private key and certificate, if not provided generates a keystore for you
https.keyStoreType - The key store type, defaults to "JKS"
https.keyStorePassword - The password, defaults to ""
https.keyStoreAlgorithm - The key store algorithm, defaults to the platforms default algorithm
https.trustStore - This feature hasn't been fully implemented, currently it will always use the JDKs trust store for verifying client side certificates (which you can of course configure yourself) whether you supply a value for this or not, unless you specify "noCA", in which case, it will use a trust store that trusts all certificates with no validation or verification, which is useful for if using webid client side certificat verification.




--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
James Roper
Software Engineer

Typesafe - The software stack for applications that scale
Twitter: @jroper

Ben McCann

unread,
Feb 5, 2013, 9:40:23 PM2/5/13
to play-fr...@googlegroups.com
Thanks for the info James!  So Play looks for the port and runs in SSL mode if running on port 9443?  It might be good to make it a separate option rather than port at some point.  E.g. if I want to run to Play servers locally with SSL, can I not do that today?

James Roper

unread,
Feb 5, 2013, 10:38:26 PM2/5/13
to play-framework
You can run it on whatever port you want, eg:

JAVA_OPTS=-Dhttps.port=12345 play run

in one project, and then

JAVA_OPTS=-Dhttps.port=54321 play run

in another, and you have two play servers running with SSL.

Or have I misunderstood you?

Ben McCann

unread,
Feb 5, 2013, 10:42:23 PM2/5/13
to play-fr...@googlegroups.com
Oh, I missed the "s" in your original message. Cool. Thanks!

Andrej Pancik

unread,
Feb 21, 2013, 12:10:59 AM2/21/13
to play-fr...@googlegroups.com
Hello,

those are good news. How do I generate https routes in Java? I would like to have some actions secure-only (for example sign in submit).

Thank you,

Andrej

James Roper

unread,
Feb 21, 2013, 6:06:01 AM2/21/13
to play-framework
On Thu, Feb 21, 2013 at 6:10 AM, Andrej Pancik <apa...@gmail.com> wrote:
Hello,

those are good news. How do I generate https routes in Java? I would like to have some actions secure-only (for example sign in submit).

We don't yet support this.  But please be aware that only using https for sign in is worthless, any user at a wifi hotspot will be vulnerable to having their session hijacked.  Either the whole app uses https, or none of it does.

Andrej Pancik

unread,
Feb 21, 2013, 10:39:06 AM2/21/13
to play-fr...@googlegroups.com
Thank you very much for your reply. I absolutely understand the risk of the session hijacking (when on unsecured networks). However, by principle sending plain-text password is even riskier. In any case, considering the https performance overhead all users that are not signed in can still use plain http without any risk whatsoever; without https router there is no way to switch them to https when sign in comes.

Andrej

Niklas Nylund

unread,
Feb 24, 2013, 3:25:45 PM2/24/13
to play-fr...@googlegroups.com
On Wednesday, February 6, 2013 4:33:41 AM UTC+2, James Roper wrote:
https.trustStore - This feature hasn't been fully implemented, currently it will always use the JDKs trust store for verifying client side certificates (which you can of course configure yourself) whether you supply a value for this or not, unless you specify "noCA", in which case, it will use a trust store that trusts all certificates with no validation or verification, which is useful for if using webid client side certificat verification.

Is the noCA flag supposed to work in 2.1? I tried this in our test build since we have some tests that check an external HTTPS server but it doesn't seem to work. I still get these errors,

[error] Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
[error]     at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
[error]     at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
[error]     at sun.security.validator.Validator.validate(Validator.java:218)
[error]     at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
[error]     at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
[error]     at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
[error]     at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
[error]     ... 21 more
[error] Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
[error]     at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
[error]     at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
[error]     at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)



Niklas

Niklas Nylund

unread,
Feb 25, 2013, 3:50:55 AM2/25/13
to play-fr...@googlegroups.com
I tried this in our testing environment now also, it doesn't seem to work. I get the same backtrace as previously. Is this a bug or should I put the JAVA_OPTS somewhere else?

$ export JAVA_OPTS=-Dhttps.trustStore=noCA
$ ../dev/play-2.1.0/play run

Niklas Nylund

unread,
Feb 25, 2013, 8:01:00 AM2/25/13
to play-fr...@googlegroups.com
This doesn't seem to work at all, I can't get the noCA option to work or using a keystore. It's really annoying since I do not want or need server side SSL support, I just want to call a https service with the WS library and right now I do not care about validation at all.

I tried combinations of the following options, 
https.keyStore="conf/keystore.jks"
https.keyStorePassword="foofoo"
https.trustStore="noCA"

Any ideas? How do I call a HTTPS service using WS? 


Niklas

Niklas Nylund

unread,
Feb 25, 2013, 11:16:16 AM2/25/13
to play-fr...@googlegroups.com
I keep spamming about this, sorry guys but I still can't get it to work :) I also tried adding the certificate for the remote HTTPS service to java's default key store on OS X like this, 

keytool -importcert -alias dev -file ./mycert.crt -keystore /Library/Java/Home/lib/security/cacerts

but I still keep getting the same stack trace / errors. What more is there I can try to do?


Niklas

James Roper

unread,
Feb 25, 2013, 11:20:58 AM2/25/13
to play-framework
Hi Niklas,

The https.trustStore=noCA support for Play is just for server side accepting of client side certificates, that is, client certificates sent to Play by the web browser.  It has nothing to do with making client connections from Play.

The WS API should accept any certificate by default.  The trust store for it can be configured using standard JVM properties, eg "javax.net.ssl.trustStore".  So are you using the Play WS client, or something else?  It should just work with the Play WS client, if you're using some other HTTP client, well you'll have to look up how to configure SSL for that yourself or ask on that clients mailing list.

Cheers,

James

Niklas Nylund

unread,
Feb 25, 2013, 11:36:58 AM2/25/13
to play-fr...@googlegroups.com
Hi James, 

Thank you for looking at this. Yes I am using WS to access a remote HTTPS-service. I just found this bug report on lighthouse that indicates that a check has been added for this in 2.0.4 (I upgraded from 2.0.1 to 2.1.0 when I found out about this so this may be an earlier regression), http://play.lighthouseapp.com/projects/82401/tickets/655-ws-call-wont-fail-upon-https-call-to-a-page-with-wrong-certificate

The full stack trace I get looks like this,
at play.api.Application$class.handleError(Application.scala:289) ~[play_2.10.jar:2.1.0]
at play.api.DefaultApplication.handleError(Application.scala:383) [play_2.10.jar:2.1.0]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anon$2$$anonfun$handle$1.apply(PlayDefaultUpstreamHandler.scala:132) [play_2.10.jar:2.1.0]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anon$2$$anonfun$handle$1.apply(PlayDefaultUpstreamHandler.scala:128) [play_2.10.jar:2.1.0]
at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10.jar:2.1.0]
at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10.jar:2.1.0]
java.lang.RuntimeException: java.net.ConnectException: General SSLEngine problem to https://api.gomob.fi/....
at play.libs.F$Promise$6.apply(F.java:401) ~[play_2.10.jar:2.1.0]
at scala.concurrent.Future$$anonfun$map$1.liftedTree2$1(Future.scala:253) ~[scala-library.jar:na]
at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:249) ~[scala-library.jar:na]
at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:249) ~[scala-library.jar:na]
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:29) ~[scala-library.jar:na]
at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.liftedTree1$1(BatchingExecutor.scala:67) ~[akka-actor_2.10.jar:na]
java.net.ConnectException: General SSLEngine problem to https://api.gomob.fi/.....
at com.ning.http.client.providers.netty.NettyConnectListener.operationComplete(NettyConnectListener.java:100) ~[async-http-client.jar:na]
at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:428) ~[netty.jar:na]
at org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:414) ~[netty.jar:na]
at org.jboss.netty.channel.DefaultChannelFuture.setFailure(DefaultChannelFuture.java:381) ~[netty.jar:na]
at org.jboss.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1307) ~[netty.jar:na]
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1186) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Handshaker.java:1015) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:485) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:753) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:721) ~[na:1.6]
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:607) ~[na:1.6]
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1118) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1528) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:243) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136) ~[na:1.6]
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323) ~[na:1.6.0_37]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217) ~[na:1.6.0_37]
at sun.security.validator.Validator.validate(Validator.java:218) ~[na:1.6.0_37]
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209) ~[na:1.6]
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249) ~[na:1.6]
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174) ~[na:1.6.0_37]
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238) ~[na:1.6.0_37]
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318) ~[na:1.6.0_37]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217) ~[na:1.6.0_37]
at sun.security.validator.Validator.validate(Validator.java:218) ~[na:1.6.0_37]
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126) ~[na:1.6]

Niklas Nylund

unread,
Feb 26, 2013, 3:00:42 AM2/26/13
to play-fr...@googlegroups.com
I am not sure if this is a bug yet or not but googling the stack trace I ran into this Oracle blog post, 
https://blogs.oracle.com/gc/entry/unable_to_find_valid_certification. It talks about this problem and supposedly you can solve it by using a free tool called InstallCert but the link is dead (however I found the code from here http://nodsw.com/blog/leeland/2006/12/06-no-more-unable-find-valid-certification-path-requested-target). Anyway, according to this tool our certificate seems valid (chrome and other browsers also detect it and are able to validate it) but for some reason Play's WS lib chokes on it. I am completely lost on how to investigate this further so any advice is appreciated, this currently blocks us from upgrading to 2.1 as we did not see these issues in 2.0.1.

Output of the InstallCert tool,

$ java InstallCert api.gomob.fi
Loading KeyStore jssecacerts...
Opening connection to api.gomob.fi:443...
Starting SSL handshake...

No errors, certificate is already trusted

Server sent 1 certificate(s):
....





Niklas

Niklas Nylund

unread,
Feb 27, 2013, 10:20:00 AM2/27/13
to play-fr...@googlegroups.com
I'll post this here if someone else runs into this issue also.

Finally I found a work around for this, the most likely cause was that one of certificates in our chain was not up to date or missing from the system wide Java keystore. Anyway, I found a hint in the Scala documentation that one can instruct WS to accept all certificates, this is completely missing from the Java documentation!

Anyway, it seems to work to add ws.acceptAnyCertificate=true to your application.conf.



Niklas Nylund

David P.

unread,
Apr 10, 2013, 3:03:09 PM4/10/13
to play-fr...@googlegroups.com

So I was able to get all of this working today. Seems pretty good so far.  But how do I then get the Client's Certificate.

I know that in Servlet-land, I could just call something like request.getAttribute("....X509Certificate");

I have a requirement for knowing the user's authenticated DN.

Thanks,
   David Patrick

Ryan Means

unread,
May 1, 2013, 10:39:02 AM5/1/13
to play-fr...@googlegroups.com
Is there a way to disable play from also starting up in HTTP mode as well? i.e. I provide a port for https, but I do NOT want to listen for HTTP requests what-so-ever?

David P.

unread,
May 1, 2013, 10:48:01 AM5/1/13
to play-fr...@googlegroups.com
Message has been deleted
Message has been deleted
Message has been deleted

sts2055

unread,
Jun 9, 2013, 12:01:21 PM6/9/13
to play-fr...@googlegroups.com
I am trying to learn how to setup ssl for the very first time, so I'm new to the whole thing.
I followed the instructions and added the following to my application.conf:

https.port=9443
https.keyStore="conf/keystore.jks"
https.keyStorePassword="foo"
https.keyStoreAlgorithm="RSA"


I then try to launch the server locally in prod using 'play start', but the output I get is that the server only listens for http on 9000.
When using JAVA_OPTS=-Dhttps.port=9443 play run it always tells me that it listens on both http as well as https on 9443.

I also tried launching the server in dev mode using 'play run 9443' and get the standard output telling me that play listens for http on 9000. After stopping the server, I get the following output:
[error] Expected key
[error] 9443
[error] ^

This makes me think that there is a problem with my keystore file.
I generated the jks file using:
keytool -genkey -alias myalias -keyalg RSA –keysize 2048 -keystore keystore.jks

and the request using:
keytool -certreq -keyalg RSA -alias myalias -file certreq.txt -keystore keystore.jks

At this stage I am uncertain about where the actual problem lies.
Is it as I suspect that there is a problem with my keystore.jks?
Do I have to copy the .key to ../conf folder?
Are there any system properties that I need to add to make it work?
Message has been deleted

sts2055

unread,
Jun 11, 2013, 10:21:14 AM6/11/13
to play-fr...@googlegroups.com
Hi Sears,

Thanks for your post. I was stuck so it helped a great deal so far.

I followed the steps in your post and did the following to launch play:
play -Dhttps.port=9443 -Dhttps.keyStore="conf/keystore.jks" -Dhttps.keyStorePassword="apassword" run

When adding -Dhttps.keyStoreAlgorithm="RSA" it would generate the same error as the one you got.
It works for me when leaving it out. Since I run it locally and the certificate is my website's the only thing it now complains about when connecting is:
 • Server's certificate does not match the URL.
Which I am guessing is to be expected?

Now the only thing that seems left to do is to figure out how to deploy it to heroku and start the server in ssl.
Am I correct to assume that I need to add the system parameters to the Procfile?

All the very best,
Stefan


On Monday, June 10, 2013 8:31:34 PM UTC+2, Sears Merritt wrote:
Hi All,

I'm new to Play and in the process of configuring SSL. I can successfully run in dev mode with a self signed certificate, but when I try to use a signed certificate the initial client handshake fails and Play generates the following stack trace:

play - Error loading HTTPS keystore from /Users/sears/Projects/PathOp/conf/pathop.jks
java.security.NoSuchAlgorithmException: RSA KeyManagerFactory not available
at sun.security.jca.GetInstance.getInstance(GetInstance.java:159) ~[na:1.7.0_11]
at javax.net.ssl.KeyManagerFactory.getInstance(KeyManagerFactory.java:139) ~[na:1.7.0_11]
at play.core.server.NettyServer$PlayPipelineFactory$$anonfun$sslContext$1.apply(NettyServer.scala:74) [play_2.10.jar:2.1.1]
at play.core.server.NettyServer$PlayPipelineFactory$$anonfun$sslContext$1.apply(NettyServer.scala:62) [play_2.10.jar:2.1.1]
at scala.Option.map(Option.scala:145) [scala-library.jar:na]
at play.core.server.NettyServer$PlayPipelineFactory.sslContext$lzycompute(NettyServer.scala:62) [play_2.10.jar:2.1.1]

I've configured ssl support as follows:

//generate a csr
keytool -certreq -alias pathop -keyalg RSA -file pathop.csr -keystore pathop.jks

//load root and intermediate certs
keytool -import -alias godaddy -keystore pathop.jks -file gd_bundle.crt

//load signed cert
keytool -import -alias pathop -keystore pathop.jks -trustcacerts -file pathop.com.crt

//launch play with system parameters to run ssl
sudo ../../jars/play-2.1.1/play -Dhttps.port=443 -Dhttps.keyStore="conf/pathop.jks" -Dhttps.keyStorePassword=REDACTED -Dhttps.keyStoreAlgorithm="RSA" run

Any insight into this error would be greatly appreciated.

Regards,
Sears Merritt

sts2055

unread,
Jun 11, 2013, 10:26:06 AM6/11/13
to play-fr...@googlegroups.com
So the Procfile would have to look something like this?:

web: target/start -Dhttp.port=${PORT} -Dhttps.port=9443 -Dhttps.keyStore="conf/keystore.jks" -Dhttps.keyStorePassword="apassword" -DapplyEvolutions.default=true -Ddb.default.driver=org.postgresql.Driver -Ddb.default.url=$DATABASE_URL ${JAVA_OPTS}

sts2055

unread,
Jun 11, 2013, 10:44:16 AM6/11/13
to play-fr...@googlegroups.com
Well, I tried it out and it doesn't work it seems =)
When contacting my website via https it uses Heroku's certificate

From what I can gather ssl on heroku is only available via an addon: 

Kevin Meredith

unread,
Jan 18, 2017, 11:19:42 AM1/18/17
to Play Framework
Play will generate a private key and self signed certificate, which obviously your browser will balk at with a big red warning
So, in DEV mode, traffic (HTTP requests and responses) will be encrypted via a self-signed certificate, as I understand.

However, the browser will "balk at with a big red warning" since the brower's trust-store, i.e. certificates that it trusts, will not include the self-signed cert?

And, since it does not trust it, it will ask the user to "Proceed Anyway" even though it's not a trusted certificate?

Lastly, this approach is not Prod-ready since, if the web site were hacked, then we could be blindly trusting the hacker's certificate?

Please confirm or correct my understanding. 

Marcos Pereira

unread,
Jan 18, 2017, 12:23:07 PM1/18/17
to play-fr...@googlegroups.com
Hey Kelvin,

So, in DEV mode, traffic (HTTP requests and responses) will be encrypted via a self-signed certificate, as I understand.

HTTPS requests and responses.
 
However, the browser will "balk at with a big red warning" since the brower's trust-store, i.e. certificates that it trusts, will not include the self-signed cert?

Correct.
 
And, since it does not trust it, it will ask the user to "Proceed Anyway" even though it's not a trusted certificate?

Correct.
 
Lastly, this approach is not Prod-ready since, if the web site were hacked, then we could be blindly trusting the hacker's certificate?

Correct. This approach must not be used in production. Even if you don't want to buy a trusted certificate for production, you can use https://letsencrypt.org/ instead of creating a self-signed certificate.

Best,

-- 
Marcos Pereira
Software Engineer, Lightbend.com

Reply all
Reply to author
Forward
0 new messages