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

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.

Related

JGiven show acceptance test running line by line

Is it possible to use JGiven (with or without Spring support) to retrieve the statements before / during execution? For example, if we had a fairly typical login acceptance test i.e.
public class LoginFeatureTest extends SpringScenarioTest<GivenIAmAtTheLoginPage, WhenILogin, ThenTheLoginActionWillBeSuccessful> {
#Test
public void my_login_test() {
given().I_am_a_new_user()
.and().I_am_at_the_login_page();
when().I_login_with_username_$_and_password_$("dave", "dave123");
then().the_home_page_is_visible();
}
}
Is it possible to get something access to the following information?
My Login Test (start)
Given I am a new user
and I am at the login page
When I login with username dave and password dave123
Then the home page is visible
My Login Test (end)
i.e. what i'm looking for is: -
The name of a scenario method + all it's given, when, then and and statement calls _(formatted via JGiven formatting).
When each scenario method starts at run-time.
When each given, when, then and and executes at run-time.
When the scenario method ends.
This will give me the ability to visually show in a UI (a) exactly what is going to execute and (2) it's current position during execution (with durations).
12:00:01.012 [ My Login Test (start) ]
12:00:02.035 23ms Given I am a new user
12:00:02.051 16ms and I am at the login page
----> When I login with username dave and password dave123
Then the home page is visible
[ end ]
I'm thinking Spring AOP might come to the rescue here? Or does JGiven provide anything useful buried in it's code?
At the moment there is no possibility to do that. I have created an issue for that: https://github.com/TNG/JGiven/issues/328.
It should not be too difficult to implement this as there is internally already a listener concept. If you are still interested you could propose an API and integrate the mechanism in JGiven.

Grails Spring Security Static Rules

I want all users to be authenticated before accessing my application. Following is the setting in Config.groovy:
grails.plugin.springsecurity.controllerAnnotations.staticRules=[
"/**": ["ROLE_ADMIN"],
"/login/auth": ["permitAll"]
]
The reason I put "/login/auth": ["permitAll"] is that any user can have a chance to log in and be authenticated. However, when I access http://localhost:8080/myapp/, it redirects to http://localhost:8080/myapp/login/auth and throws the error: The page isn't redirecting properly. Can you please advise what mistake I have committed here?
For first you must say to spring security what type of mapping you will be use.
grails.plugins.springsecurity.securityConfigType = 'InterceptUrlMap'
For second 'permitAll' changed to 'IS_AUTHENTICATED_ANONYMOUSLY'
And for third, if spring security find /** he didn't see another under this line. So your code must be like this:
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = [
"/login/auth": ["permitAll"],
"/**": ["ROLE_ADMIN"]
]
TrongBang and Koloritnij are on the right track. But they're not completely correct in the context of your question. They're suggesting that you switch to a different authentication setup. (Which that will work but it doesn't solve the problem in the context of your setup.)
If you wish to keep the annotations, you're going to have to call out the controller that OAuth uses.
‘/springSecurityOAuth/**’: [‘permitAll’]
The plugin maps that controller path, but the static rules still interprets the controller and methods from that.
This took some digging for me to find this out. I had your same issue, and I blogged about this (and it includes some of the details about how the Spring Security Oauth plugin works.
http://theexceptioncatcher.com/blog/2015/04/spring-security-oauth-the-missing-instructions/
The solution from Koloritnij is correct. However, it threw the following error when using SecurityConfigType.InterceptUrlMap:
ERROR: the 'securityConfigType' property must be one of
'Annotation', 'Requestmap', or 'InterceptUrlMap' or left unspecified
to default to 'Annotation'; setting value to 'Annotation'
I have changed it to 'InterceptUrlMap' only and it worked:
grails.plugins.springsecurity.securityConfigType = 'InterceptUrlMap'
grails.plugins.springsecurity.interceptUrlMap = [
"/login/auth": ["permitAll"],
"/**": ["ROLE_ADMIN"]
]

before filter issue in padrino

I'm trying to create a chain of before filter in padrino that look like this of which look like this
before do
set_current_user
track_order_ip
!current_user and pass
## don't allow the next filter other filter to run if no current user
customer_inactivity!
skip_enforce!
## so the theory is this if a users is is not enforced he should not be allowed to execute enforce! before filter
enforce!
end
Now all filter would execute in chain but if the current_user is not present I wish to drop(i.e pass) the filter chain processing which is taken care by this (!current_user and pass) code
But trying to do something like this in padrino cause the app to redirect the same route multiple time and then break with following error.
ArgumentError at /myaccount/users/authenticate
uncaught throw :pass
at
!current_customer and pass
What I'm find weird and what I'm not able to understand is , why? it not working in Padrino(since I know Padrino internally uses Sinatra) because I did wrote a proof of concept similar application in sinatra (can be found over here) and that just seem to work out of box without any issue
Lastly here the padrino code
Now any one can give me some pointer as too what I'm doing wrong in padrino that is implemented correctly in the proof of concept sinatra app
Thanks

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

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

Compojure/Ring: Why doesn't a session with cookie-store survive a server restart?

I have a compojure app that uses the ring session wrapper to store the OAuth token associated with the current user. I would like for this token to remain available when the server restarts, so that I don't have to go through the auth process each time.
I assumed that using the cookie-store instead of the default memory-store would help, but it does not. What am I missing?
This is the relevant part of the code:
(defn auth-callback-handler
[session {code :code}]
(let [token (retrieve-token code)]
(-> (redirect "/") (assoc :session (assoc session :token token)))))
(defroutes app-routes
(GET "/" {session :session} (root-handler session))
(GET "/auth-callback" {session :session params :params} (auth-callback-handler session params))
(route/not-found "Not Found"))
(def app
(-> (handler/site app-routes)
(wrap-session {:store (cookie-store {:key "a 16-byte secret"})})))
The function root-handler uses the token to decide if someone is logged in or not, but does not return anything in the way of session info.
The issue is that you have 2 wrap-session middlewares in your app, as the handler/site comes with one. This is causing the encrypt/decrypt to be run twice. To configure the compojure session handle use:
(def app
(site app-routes {:session {:store (cookie-store {:key "a 16-byte secret"})}}))
Also, perhaps you would be interested on some of these projects, which implement the ring SessionStore protocol:
https://github.com/sritchie/couch-session
https://github.com/wuzhe/clj-redis-session
https://github.com/rmarianski/servlet-session-store
To make the last one persistent you will need to check the documentation of your servlet container of choice.

Resources