Integration Test with Transactional - spring-security

I have the following scenario/system.
A Rest Service proposal, behind the Spring security configuration, with Spring JPA and a postgres DB.
Now my scenario makes a
login of a user 1
logout of user 1
login of user 1
make a request on a resource
logout of user 1
login of user 2
make a request on a other resource
logout of user 2
This all on a test method (I know it can be wrong doing that).
Now that was confusing me is that he had some encryption/decryption methods to retrieve user and they're fields. Now what I saw was that on the firs login of 1 the user goes through the decryption code (this is OK), after in the second login of user 1 we don't goes through the decryption code (but the user was logged in). (this is a little bit strange, I has expected that the user goes though the decryption code), after that by accessing the resource also user 2 is decrypted (this is correct).
But by logging in the user 2 the user don't pass on the decryption code (and I have an exception because the fields that normaly are encrypted, now are decrypted) The exception can be OK, but not the fact that the fields are decrypted.
Now the exception is thrown only when I set the test under #Transactional.
When I make the test not #Transactional then the behavior sames to be correct (evry time by login the user is decrypted.)
Now I think: "it is logical that the test does not be #transactional", but I have a bit fear that I have a caching problem: can this be? I dont'have any caching configuration (only for ACL, not for user management).
Also the second level cache of hibernate is turned off.
Is there a way to find out if some caching or inmemory strenght are intrcate?
Txs

Without seeing your actual code and configuration, I can't really assess exactly what is going on; however, I can provide you the following general information...
If you are simulating a use case that models different external connections to your application (i.e., two independent users connecting to your application via a REST API), then you will not want to annotate your test method with #Transactional.
Annotating a test method with #Transactional causes all of the method invocations within your test method to be executed within the same transaction [0]. Thus, any items stored in the first-level cache by JPA will be cached across method invocations within the scope of your test method.
Hope this helps!
Sam
[0] This statement is based on the assumption that none of the methods invoked directly or indirectly by your test method are configured to run within a new transaction.

Related

Capybara session not preserved with an api callback

I have a rail 5 app with capybara 2.13 feature specs. One spec completes a three-part transaction flow that includes a redirect url to a callback path in the app. I save the transaction ID in the session as session[:current_transaction_id] and then use this to look up the transaction when processing the callback. This works fine in development but when testing with capybara the session hash is missing :current_transaction_id.
I've unsuccessfuly tried wrapping my spec as described in
https://github.com/teamcapybara/capybara#using-sessions
Capybara.using_session("User session") do
# log in and complete a transaction
end
How can I get the session to persist through the given spec?
Capybaras using_session doesn't refer to the session you're asking about. It refers to a browser or browser/app pair instance used by Capybara and would commonly be used if you needed to simultaneously log two different users into an app while testing it (chat, realtime status updates, etc).
When using cookie based sessions you need to make sure the original (sub)domains originally being visited (where you set the transaction id) and the one redirected to are the same (at least to the level the session cookie is set at). If they aren't the session cookie will no longer be valid for the redirect request (and not sent) and hence the transaction id not available.

User.IsInRole fails for one action but not for another

I've put a custom authorize attribute into my MVC application, which does
if (!this.Roles.Split(',').Any(filterContext.HttpContext.User.IsInRole))
and if true it will redirect you to unauthorised.
I put this attribute on my controller at controller level.
One action works fine, and in one action I get unauthorised.
Is there some bug or problem in the role system? I've read that logging out and in can force some cache to refresh or something, however the system I am using authenticates with your domain credentials so there is no way to log out.
I've tried restarting the app pool and deleting my session cookie but nothing has worked.
Has anyone experienced this specific issue before or has some guidance on perhaps flushing any caching related to it (assuming it's a caching issue)?
ETA: Another user on the system gave himself the role required for the controller and both actions work fine for him. So perhaps my user is somehow bugged. This is on UAT so slightly more difficult to debug than running on my local machine (which works fine).
ETA2: I'm pretty sure this is a caching issue, as going to the URL with ?1=1 in the query string, it works. I'm unable to invalidate the cache though. This may be a problem in the future when assigning roles to people.
First, we need more code before we could possibly give you any definitive answers. However:
Caching could be a problem. If you're using anything like OutputCache, you should ensure that you're using VaryByCustom and somehow including the user's id or other identifying token in the custom string returned.
If you're adding roles to users, you must either log the user out and sign them back in, or otherwise invalidate their authorization. In Identity, for example, you can simply invalidate the security stamp, which will cause the user to be reauthorized, updating things like claims or roles that have changed since they signed in.

Asp.Net MVC Antiforgery validation fails when non-null usernames differ...is that reasonable?

My question is about the MVC Antiforgery system (described here).
Consider a simple app which posts todos to /Todo/Create. The corresponding action method has the ValidateAntiForgeryToken attribute. Consider the following client workflow:
User A logs on and goes to the page to create a todo, but doesn't do it yet.
User B (physically on the same computer) opens a new tab in the same browser, logs out of User A's account, logs in as User B. The browser then gets User B's validation cookie.
Some time later, User A switches back to their original tab and hits 'create' on the todo they were making.
In this scenario, the Antiforgery verification will not pass because the form token was meant for User A, while the validation cookie is for User B.
I'm sure there are valid security reasons for this behavior (e.g. a script on another site that manages to login as malicious user so that the 'todo' data is posted to their account instead), but it doesn't stop the above scenario happening for my legitimate users sometimes.
My questions are:
Is there a 'best practices' way to handle this scenario? Is it usually just a case of showing a custom error, telling them to reload the page and/or login again etc?
Is there any way to know when the out-of-the-box MVC Antiforgery system runs into this error? It seems to only ever throw the same kind of Exception (HttpAntiForgeryException). Would I need to revert to using/modifying their source?
I see two ways of handling it:
Use Javascript callback to the server before hitting a button to detect if the user is still logged in. If not - display him a message. It should be relatively easy to do this. But it requires one additional call, and little bit more time to execute your request.
One solution to avoid callbacks could be using html 5 localStorage (and you can support that on other browsers using modernizr, for example). It is shared between tabs. But I'm not sure if this approach is good. Additional research required.
Catch HttpAntiForgeryException on the server, check if the user is logged in. If the user is not logged in, display him a message.
Usually approach (1) is used. On banking websites they detect with JavaScript when you logged out in other browser tab.

Using a Custom Single Sign On Authentication Service with Spring Security Core Plugin

I'm working on a Grails application and want to integrate with a custom single-sign-on service (not CAS, but similar). I'm struggling to find all the pieces that I need to customize to make this happen. Can someone explain to me a general outline as to what I need to use to accomplish this? I've read the documentation on the plugin, but it assumes I know which beans to override and where to put all the needed files.
I've block-quoted what I think needs to be done based on my research below each point.
Order of Operations
1- The user requests secure content (everything is secure in the application for now)
I believe this setting is in the Config.groovy file:
grails.plugins.springsecurity.rejectIfNoRule = true
grails.plugins.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugins.springsecurity.interceptUrlMap = [
'/**':['ROLE_ADMIN']
]
2- Spring Security checks to see if the user has a specific value set in a cookie provided by the authentication service
I'm guessing I need to create an authentication filter, but I don't know where to put it or what it should look like.
If they don't, the user is redirected to this custom SSO service, they login, once authenticated, the user is redirected back to my application (with a new cookie set)
3- Spring security checks for the cookie value and validates it against the custom service (via HTTP POST)
From some research, I think that I need to use PreAuthenticatedProcessingFilter, but I haven't been able to find any examples of how to do this.
4- The custom service returns a series of name/value pairs, a user then needs to be created in the local application database (or the timestamp of "lastLoggedIn" is updated if they user's data is already in the database)
I believe this is done in the same PreAuthenticatedProcessingFilter as number 3 or in a GrailsUserDetailsService
5- The user's authentication is cached in the session for a period of time (6-8 hours) so that re-validation against the SSO service doesn't need to occur every time the user requests a new resource.
I'm not sure if this is something that's done inherently or if I need to add code to do this (and also set the session timeout)

ASP.NET MVC: A PreAuthorize-like event, Good throttle point for concurrent logons?

I want to allow a new login to 'kick' a prior login session by the same account, in ASP.NET MVC.
It seems pretty clear that I'll give each browser a cooking representing the session ID. I'll track the currently active session ID in a server-side cache. If an already-active user attempts to log in, I'll verify the business logic (username, password, has been at least 15 minutes since last activity), and then update the active session ID cached at the server.
Now my issue is, a browser is holding an invalid session ID. What is the best point for me to inject a rejection or redirect to sign-in for this scenario?
I could modify the AuthorizeAttribute, but it seems like there should be a cleaner place to do this that won't require me to search and replace all my Authorize attributes, for example via a Global.asax event, or a controller event (I've already extended Controller in my project).
For example, if PreAuthorize existed, I would write some code there to test the request's cookies for a valid user/session ID pair, and if it didn't exist, I could simply remove the authentication cookie from the request, which would result in a standard unauthorized redirection.
So after a bit of research, it seems that a custom AuthorizeAttribute would typically be the correct approach. However, in my case, since I already had a custom role provider implemented, it was just a line of code to do it there. This also benefited me because I only wanted session concurrency for a single role. A side effect is that any use of web.config to control access to static files by role is also in-effect for session concurrency.

Resources