I have my luminus app deployed to heroku with an SSL certificate- so going to https://www.my http://app.com (fake link) works and shows the lock icon in browser But if I access the link without the https:// appended to the URL, http is used and there is an “unsecured connection” warning. Is there a way in luminus to redirect all requests to my URL to use https?
Actually there is a much easier way, almost trivial. It is possible to enable a Strict-Transport-Security header and redirect to HTTPS using the Ring config. No need to add ring-ssl.
Just add the lines
(assoc-in [:security :hsts] true)
(assoc-in [:security :ssl-redirect] true)
like this in your middleware.clj:
(wrap-defaults
(-> site-defaults
(assoc-in [:security :anti-forgery] true)
(assoc-in [:session :store] session/store)
(assoc-in [:security :hsts] true)
(assoc-in [:security :ssl-redirect] true)))
wrap-internal-error))awesome. Trivial if you know about it 🤷♂️ - where did you find this? thanks!
True 🙂 I was looking into what function wrap-defaults from ring.middleware.defaults does, that’s where I found it.
Only problem right now is that it is enabled in dev mode as well, and https://localhost:3000 does not work
I was wondering if that would be a problem
Probably a cond-> that checks the env var
let me try something
Yeah… (assoc-in [:security :ssl-redirect] (get defaults :ssl-redirect true))))
and then :ssl-redirect false in env.clj
ahhh nice
I had a gnarly cond-> going lol
It’s probably better to disable HSTS for localhost as well
I had it enabled and got redirected (although broken), but now my browser will immediately redirect to HTTPS due to HSTS… the max-age is set for 1 year — I guess I should find out how to reset this 😂
lolll
Are you sure about (get defaults :hsts true)? This will default to true even if it isn’t present
My idea was that it isn’t present on production, therefore to enable it on production, it must be true
I’m trying this out:
(defn wrap-base [handler]
(let [config-file (:conf (source/from-system-props))]
(-> ((:middleware defaults) handler)
(wrap-defaults
(-> site-defaults
(assoc-in [:security :anti-forgery] false)
(assoc-in [:session :store] (ttl-memory-store (* 60 30)))
;Enable HTTPS redirect...
;TODO - look into these settings and what they mean:
(assoc-in [:security :hsts] (if (= config-file "dev-config.edn")
false
true))
(assoc-in [:security :ssl-redirect] (if (= config-file "dev-config.edn")
false
true))))
wrap-internal-error)))ack - assoc’ing in ssl-redirect broke my page when deployed 🌚
your version looks a bit too complicated in checking the config file name to figure out whether it’s dev or not
what exactly broke your page?
This page isn't redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS You don’t have this problem in production?
“More than 20 redirections”
https://stackoverflow.com/questions/30689577/clojure-wrap-ssl-redirect-on-heroku
You’re faster than me, I’m deploying… 😄
Ah ok, seems like the App does not know it’s being accessed via HTTPS already and therefore already redirects. I will have the same issue then.
Take a look at this defaults.clj - the wrap-defaults function
I think it’s already doing this for us, we just need to set up the config correctly
Yeah, I was just looking at it too, try setting :proxy to true to enable wrap-forwarded-scheme
yah, deploying now to see if it works 🤞
Works for me now 👍
Can I see yr wrap-base fn?
1st redirect is from the app (HTTP 301), on a subsequent visit it’s a browser redirect (HTTP 307)… as expected
(defn wrap-base [handler]
(-> ((:middleware defaults) handler)
(wrap-defaults
(-> site-defaults
(assoc-in [:security :anti-forgery] true)
(assoc-in [:session :store] session/store)
(assoc-in [:security :hsts] (get defaults :hsts true))
(assoc-in [:security :ssl-redirect] (get defaults :ssl-redirect true))
(assoc-in [:proxy] (get defaults :proxy true))))
wrap-internal-error))and my config in env.clj
:hsts false
:ssl-redirect false
:proxy false})how did you know defaults would have the vals from config?
because I added them in env.clj
Can I see that?
(ns myapp.env
(:require
[selmer.parser :as parser]
[clojure.tools.logging :as log]
[myapp.dev-middleware :refer [wrap-dev]]))
(def defaults
{:init
(fn []
(parser/cache-off!)
(log/info "\n-=[myapp started successfully using the development profile]=-"))
:stop
(fn []
(log/info "\n-=[myapp has shut down successfully]=-"))
:middleware wrap-dev
:hsts false
:ssl-redirect false
:proxy false})ahhhh, I see now
I was trying to pull these from the config file. I wonder if there’s a way to do that. This works though
thanks a lot!
I would only pull things from a config file which need to change without recompilation and can be read from the environment, so e.g. database URL
but in this case the production build will never have HTTPS switched off — I guess 🙂
Ok, cool. This is the first website I’ve ever made, so I don’t really know best practices
Thanks for all your help
if you look at core.clj, there is a line like this:
(update :port #(or (-> env :options :port) %))
This is reading the port from the config file
I set up a prod-only DATABASE_URL for the postgres instance by the skin of my teeth
Got ya
😂 👍
Cool, thank you very much!
Thanks - I think I found something 😁
@esciafardini I have the same issue and would also be interested in your solution 🙂
this is what I found: https://github.com/ring-clojure/ring-ssl I haven’t tried it yet- but it’s on my todo list.
Let me know if you have any luck 🙂
maybe this helps https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls
also look at HSTS header https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
be careful with hsts, browsers are kind of strict from what I remember
bottom: line, you need to do it in your app. A high level solution is: Add a route / middleware ?! that checks schema = http . when that happens, either send HSTS and/or redirect to http . Maybe you can find a library that implements this logic ?!
please share