I have a web application using spring webflow and spring security. I have a problem with concurrency and here's the scenario.
When I log in an and go to an edit page, and when my account was already restricted for that operation, I am not supposed to be able to perform the operation already. I see that since my ROLE save in the session was loaded during log in so this would naturally happen. What's the best practice for this. Shall I query for my role and replace that in the session FOR EVERY critical operation or restricted operation? Is this not an overhead to the server?
Keep cache of <user id, timestamp> of users whose permissions were changed recently. Let cache entries expire after a twice amount of session expiration time.
Add custom filter that recognizes sessions having existing SecurityContext:
If session SecurityContext contains Principal whose user id is in the recently changed cache and session's getLastAccessTime() is earlier than a change timestamp, explicitly re-authenticate the user with a new authorities.
This solution will take care of both permissions upgrade and downgrade scenarios.
You may see a good example of user in org.springframework.security.web.authentication.switchuser.SwitchUserFilter
Related
How would I retrieve all valid sessions for a specific user? For example, if the user is logged in from multiple devices and decides to change password, or reset password. I need to be able to expire all active sessions and log the user out of all devices. This is specially important if the user is suspecting that his/her account has been compromised and needs to change the password. Currently I can retrieve RMEs but not sessions. I know this is doable from the UI but I need to put this feature in an SDK or API. Is there a curl command to easily achieve this?
Sarah,
Currently there is no endpoint that will let you invalidate all user sessions.You would need the session token of each session and then call the /json/sessions/?_action=logout REST endpoint multiple times (once per session).
That being said you can use the following class to get the list of sessions for a particular user:
com.iplanet.dpro.session.service.SessionCount
You can read the javadoc here.
There are some constraints for using this method though. Session Quota must be enabled. You can enable Session Quota on the admin console by going to Configuration -> Global -> Session page and:
Set the number of "Active User Sessions"
Turn on "Enable Quota Constraints"
To sum up, you can create your own custom endpoint that will take the User ID and invoke SessionCount.getAllSessionsByUUID(uuid) to get the list of active sessions. After that, you can iterate through the list of sessions and invalidate them one by one.
Hope this answers your question.
What Cross-Domain Single Sign-On implementation best solves my problem?
I have two domains (xy.com & yz.com) which already have their own database of users and are already implementing their user authentications separately. Recently there has been the need to implement CDSSO so that users dont have to log in each time they try to access resources from both domains.
Ideally the CDSSO implementation I hope to use should allow custom implementation of authentication, as I hope to call API's provided by both domains during authentication to confirm a user exists in at least one of the domains user database.
I've been looking at Sun's OpenSSO which seems to provide a means to extend its AMLoginModule class yet this seems to be a long thing and more annoyingly they seem to stick to GlassFish.
I've also considered developing a custom CDSSO to solve our needs. Is this advisable?
Is this achievable using Suns OpenSSO considering the disparate user database as I there will be no need to make use of the User db that OpenSSO requires?
Are there any simpler means of achieving what I intend to achieve?
In addition both applications which exist on the two domains were developed using PHP. How does this have an effect considering Suns OpenSSO is based on Java EE?
Are there any clearly specified steps on implementing OpenSSO and or any other SSO implementations from start to finish?
I suggest you to use simpleSAMLphp in order to deploy an Identity Provider and 2 Service Provider (for each app).
SimpleSAMLphp allows you to select multiple authentication source and is not hard to build your own authsource that consults the 2 databases.
My experience in SAML says that the fact of not consolidating the Identity of the user in 1 unique authsource is a bad idea due several reasons:
* identity conflicts: what happen if you have the same user registered with different mail (if that is the field yoy use to identify the user) and you try to access? You could be logged in different account each time.
* what happen if you add a 3rd service, do you gonna add a 3rd database
* what happen if user change its data in one app, the other gonna be no synched?
* what happen if user uses different passwords?
I recommend you to execute a migration process before adding the SAML support and build a unique database for all your identities and unify the registration/edit profile/password recovery process of both sites in one.
SimpleSAMLphp has good documentation, but I can provide to you any documentation related to the process that I suggested.
Assume I have two web applications and single STS service:
1. Administration portal where I can grant privileges to users.
2. Sales portal where users can do things based on those privileges.
Now assume I have STS that provides security tokens with 8 hours expiration to Sales portal. Token contains claims that carry information about privileges for user, among other things.
Now imagine a scenario where on the Administration portal privilege is removed for the user and change has been saved to the database. Since user is already logged in to Sales portal with security token that has not yet expired, Sales portal will not be aware that privilege has been removed.
Question is - how to handle this scenario. To me the only solution that I can see here is complete removal of STS, but I'm looking for a smarter way to handle this.
Is there a better approach to this out-of-sync issue?
Removing the STS is a little bit drastic :-). You have it for a reason (SSO, federation, etc). You have a few options: decrease the expiration time of the token to a reasonable value for the volatility of your changes (8 hours might be excessive), or move the sensitive authorization information (e.g. privileges) to the app so it is checked each time.
You can do "claims enrichment" at the app level (through a custom AuhtenticationManager in WIF) and still use claims model from your app code.
Technically there's no synching between the app and the STS. The Token is a snapshot of user attributes at the time of issuance and valid until it expires.
I have a Microsoft Dynamics CRM implementation (either 2010 or 2011 in not 100% sure). This CRM system needs to call our internal service framework services from plug ins.
In order to call the service framework we use an API with a login method that goes to an STS and gets a security token. This is per user to authenticate and get that users claims. The login call returns an IPrincipal object that we put on the Thread.CurrentPrincipal property and from then on we can call services with our framework and the user is authenticated for each call because of the principal on the executing thread.
In an asp.net website we usually log the user in and immediately go to the STS to get a token, then cache that token for the user in session because the login is not something we want to do every time we want to call a service.
How would I do this with a CRM plugin. Do I have access to a per user session store? I noticed IServiceProvider is passed in as a parameter, can I add services to this container and solve this problem in a service with a thread safe dictionary of some kind? I know very little about CRM development and Im even wondering if a plugin is the right way to do this?
The plugin is created and cleaned on a regular basis, you wouldn't be able to store anything for any period of time (or at least store it and rely on it being there).
You could potentially store this in a custom entity though if that is something that is possible?
e.g.
- Plugin is called for x event
Get CallingUser from Plugin
Search for MyCustomSTS entity for the User
See if Token exists and/or has expired
If you have the token - hooray
If not, run off and grab one
This may, of course, take longer than reauthenticating each time!
Is the token you are fetching for individual users or for the service account?
Ideally you should write your plugin to be stateless.
Write a Plug-In
For improved performance, Microsoft Dynamics CRM caches plug-in instances. The plug-in's Execute method should be written to be stateless because the constructor is not called for every invocation of the plug-in. Also, multiple system threads could execute the plug-in at the same time. All per invocation state information is stored in the context, so you should not use global variables or attempt to store any data in member variables for use during the next plug-in invocation unless that data was obtained from the configuration parameter provided to the constructor. Changes to a plug-ins registration will cause the plug-in to be re-initialized.
If you are fetching a token for individual users you could save that in CRM somewhere but that approach has a number of problems as glosrob suggests. In this case its probably just best to authenticate every time.
If its for the service account, you could go against the recommendations of Microsoft and cache the token in memory. Logically as long as your write your code to be happy with randomly loosing and having to reacquire its token you should be okay.
I agree with people who says that each time authentication is better solution, but if you need storage for tokens, you can create custom CRM entity and write logic which will work with tokens stored in CRM from plugins.
Using a strongly typed dataset and its related table Adapters, normally when I want the changes to pass back, just pass it the table and let it do all the work.
What are some easy ways to enforce security roles on the application user as to which fields they can insert/update/delete when the database is using an application ID instead of user level security?
Do I have to go row by row and check each row against what this particular user is allowed to do (by checking the current version of every field against it's proposed version against their role's permissions?
I believe the first level of security would be locking down the columns on the UI a particular user is not supposed to modify, but what about at the data level? Is there a nice way to do this?
Is this easier in linq-to-sql?
First, are you asking about actual security or just control/saftey/fool-proofing (ie stopping users from doing something dumb)?
If you are trying to enforce security try to answer some questions like who is allowed to connect to the database? where is the actual enforcement (eg, application vs connection to the database)?
For example if your application is where enforcement is placed then what if your application is compromised? Can it then connect to the database and do whatever?
For role separation I would suggest different application that are running/assigned different roles. Each role has to authenticate against the database in some way and only have access to necessary data.
In summary, ask who is doing what to whom and what if they were compromised.