In clojure/ring, how do I delete a cookie? - session

Suppose I want to delete a cookie (for example, ring's session cookie):
Making a response map like this:
{:cookies {"ring-session" {:value "kill", :max-age 1}}}
seems to work, but it feels a bit hacky.
Is there a clean way to just delete it?

That seems like quite a reasonable way of going about it. Many web a applications delete cookies be replacing them with one that is about to expire. The :max-age 1 syntax makes this look much more elegant than it does in, for example, Javascript.

I was using wrap-session and the other handlers in ring.middleware.
Setting the cookie to max age was not working in the response since it was just being overwritten (very frustrating to diagnose!)
This is what I needed to do:
(defn clear-session! [resp]
(assoc resp :session nil))
source

ringseems do not support this, but you can send the user agent a new cookie with an Expires attribute with a value in the past.
more info

If you are using ring-session, this could be another way to do delete cookie.
(def epoch (ZonedDateTime/ofInstant Instant/EPOCH ZoneOffset/UTC))
(def response {:status 200,
:body "{\"message\":\"ok\"}",
:session nil,
:session-cookie-attrs {:expires epoch}})

Related

Cache just doesn't seem to work in clojure, what is the way to use it?

I'm working on a simple project that shows some data that I'd like to see everyday. This will go on to my raspberry-pi. I'm using a free api that has a limit on requests so I thought I'd cache the requests so I don't spam the API. Here is what I've got so far:
(def KEY "Cache-Key")
(def CF (cache/ttl-cache-factory {} :ttl 43200)) ; 12 hour cache
(defn get-data-from-api
[url]
(let [response {:cache true :value 1}]
(println "---> getting from http")
response))
(defn get-data
[url]
(cache/lookup-or-miss CF KEY (get-data-from-api url)))
According to this link, this is all that is required. Except:
my get-data function always gets it from the api (the println I added to debug gets printed always). The cache is being added just fine, just doesn't seem to fetch and return
The get-data doesn't return anything. So when I do curl http://localhost:3001/display I get an empty response.
Am I using the cache correctly please?
The last value to lookup-or-miss must be a function that will be called on a cache miss. In your code, you're first calling the function and then pass its result to the lookup function, so your function will be called unconditionally (after all, lookup-or-miss is a regular function itself and not a macro - it can't dictate when its arguments are evaluated).
Even in the article you link to, they pass http-get directly and the url serves as the key, which lookup-or-miss will use as an argument for http-get by default on a cache miss.

Add custom session entries after successful authentication with Friend, Compojure, Ring

I'm trying to put together my first web app with Compojure and am using Friend for the authentication/authorization. The problem I'm having is I want to use the interactive-form workflow but also have it set a custom session value once the user logs in successfully. I think I should be creating my own workflow but wrapping the interactive-form workflow but not sure how and if that's the correct approach.
That's correct, if you want to go further and add a custom cookie here you have an usage example:
(defn friend-middleware
"Returns a middleware that enables authentication via Friend."
[handler]
(let [auth-config {
:credential-fn (partial creds/bcrypt-credential-fn db/load-credentials)
:redirect-on-auth? false
:logout-uri "/logout"
:signup-uri "/registration"
:workflows
[;; Note that ordering matters here. Basic first.
(workflows/interactive-form)
]}]
(-> handler
(friend/authenticate auth-config)
(wrap-session {:cookie-attrs {:max-age 3600} :cookie-name "my-site.com" } )
)))
https://gist.github.com/jaimeagudo/8931879
hope it helps
Answer is quite simple actually, Friend will automatically add your credentials hash (minus the password slot) to the session if authentication was a success.

Filtering sensitive data with VCR

I'm using VCR gem to record http interactions and replay them in future. I want to filter-out my actual password value in the uri request. Here's sample of what the uri looks like:
http://services.somesite.com/Services.asmx/Cabins
Username=long&Password=john&StartDate=03%2F22%2F2012&EndDate=03%2F29%2F2012
Though an explanation is provided here, I'm still not sure how to do it after a few attempts myself:
https://www.relishapp.com/myronmarston/vcr/v/2-0-0/docs/configuration/filter-sensitive-data
Any help would be appreciated.
VCR.configure do |c|
c.filter_sensitive_data("<SOMESITE_PASSWORD>") do
ENV['SOMESITE_PASSWORD']
# or $credentials['somesite']['password'] or whatever
end
end
Essentially, you give VCR a bit of placeholder text, and then the block needs to return the real password, reading it from whatever the canonical password "repository" is.
Note that the real password is only needed the first time, when the request is recorded; on subsequent runs, it can be a fake password (as long as it's the same fake password used by the code making the request).
for rails 4+, if you are using secrets.yml you might want to do
VCR.configure do |config|
Rails.application.secrets.each do |k,v|
config.filter_sensitive_data("ENV[#{k}]") { v }
end
end
now you're sure not to forget any

Sinatra sessions - why is what I put in different from what I get out?

I've got the following declared:
set :sessions, true
and then in my controller, I have:
session[$session_id] = user.session_id if save_successful
which sets the session, and then on a trip back to the server, I have:
session_id = session[$session_id]
But when I compare what I initially store in the session, I have:
a878bbd83f217daabec1b160b00bdde6 (initally)
d1e6264b87ae240be5a25a7edbcc97e5688df133cada1c7ab50661ae2f752b48 (on trip back)
Why is what I put into a session different from what I get out? and how do I make it the same???
Cheers,
Louis
I assume you meant for $session_id to be :session_id or 'session_id', variables that begin with dollar signs are global in Ruby (it is not the name of a key, but instead a globally visible reference to some object).
A good way to take a look would be to print session.inspect is the key what you think it should be?
I've posted a bug report on https://github.com/rack/rack/issues/197#issuecomment-1648851
If I use just :id instead of :session_id then it works :~)

Set Rack session cookie expiration programmatically

I'm using Rack to try to implement "Remember Me" functionality in my Sinatra app.
I'm able to set the session cookie to expire when the session ends or in X seconds time but I'd like to do both.
For example, if a user has clicked "remember me" then I wish for their session to end after X seconds. Eg, my app.rb has a line that looks like this:
use Rack::Session::Cookie, :expire_after => 2592000, #30 days in seconds
:secret => MY_SECRET
I've tried to do the following when the user logs in:
if (!remember_me)
env['rack.session.options'][:expire_after] = nil
end
However, this does not set the cookie value.
How to set this?
I was trying to do the exact same thing and I figured out what the problem for me was. The session cookie gets set on every request if you have an expire_after time set. So when you say if (!remember_me), for that request the cookie's expire time gets set to nil. However, on the very next request, the session cookie is reinitialized with an expire time of 2592000. It seems the fix is to not set a default expire_after time and instead say:
# don't set default expire time
use Rack::Session::Cookie, :secret => MY_SECRET
if(remember_me)
env['rack.session.options'][:expire_after] = 2592000
end
I have unfortunately not figured out how to have a default expire_after time and to permanently extend that time programatically.
This probably has to be done before the session is loaded.
See Rack::Session::Cookie#load_session and Rack::Session::Cookie#commit_session
Chris' answer actually didn't work for me. I found that I had to make sure that I included the original session 'options' with the new 'expire_after' value, so instead of:
env['rack.session.options'][:expire_after] = 2592000
I would use:
env['rack.session.options'].merge! expire_after: 2592000
and be sure to put the use Rack::Session::Cookie statement (without an expire_after setting) in you configure block, if you are using Sinatra.
This did the trick.

Resources