Relogging a user in with different Spring Security Authorities programmatically - spring-security

PreReq:
User logs in and is given roles got from the database using a custom implementation of userService. i.e.
authentication-provider user-service-ref="securityPolicyService"
The implemented method loadUserByUsername gets called and the roles are load for the user for the particular club they are logging into, Default one is loaded first time in.
The user then click on a different club from the UI and I call a method on a service that gets the new list of authorities for this club.
I then perform the following:
Object principle = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
SecureMember sm = (SecureMember) principle;
Authentication auth =
new UsernamePasswordAuthenticationToken(sm, null, newAuthories); <br><br>
SecurityContextHolder.getContext().setAuthentication(auth);<br>
request.getSession(false).invalidate();
SecureMember extends User from SpringFramework.
The problem is the SecureMember authorities are never updated with the new ones.
thanks
Gary

Spring Security won't store the security context if the HttpSession is null and was invalidated during the request, so if you set the context after invalidating the session (and don't create a new session), then it won't be stored.
You should see this log message if this is the case (and you have debug logging enabled).
Either create a new session or don't invalidate the original one.

Related

ZF2 Set Zend\AuthenticationService to use second session or cookie based on url or module

I have set up two user account modules - administrator and customer. My current set-up means if you log into administrator my app thinks you're logged in as a customer also. The solution I've decided upon is to create a session where the cookie path is based on the administrator url, i.e. set the cookie_path as /administrator.
In my administrator Module.php onBootstrap function I have included:
$sessionConfig = new SessionConfig();
$sessionConfig->setOptions(['cookie_path' => '/administrator']);
$sessionManager = new SessionManager($sessionConfig, null, null);
Container::setDefaultManager($sessionManager);
which sets the cookie path, but this affects the entire application; i.e. the rest of the site is cookie free because the urls do not begin with /administrator.
How do I set up my application so that the cookie_path for my administrator module is different to the rest of the application?
[edit]
What I am after is two cookies - one for admin path, and one for the rest of the application.
[edit]
I am using Zend\Authentication\AuthenticationService for ACL. What I am trying to achieve is for a user to log into the customer section of the website and do stuff, and then log into the admin panel to do stuff.
As an example, Magento will set one cookie when dealing with customer account log in, then another cookie when dealing with admin account log in.
How do I set up Zend\Authentication\AuthenticationService to use a second session or cookie based on url / module?
To set a new namespace on the authentication service, do the following:
$auth = $e->getApplication()->getServiceManager()->get('Zend\Authentication\AuthenticationService');
$auth->setStorage(new \Zend\Authentication\Storage\Session($_namespace));
In my question I wanted create a disparate session for my admin area. In my abstract controller (where I am checking the $auth details against my acl set-up) I have:
$params = $e->getRouteMatch()->getParams();
/** #var \Zend\Authentication\AuthenticationService */
$auth = $e->getApplication()->getServiceManager()->get('Zend\Authentication\AuthenticationService');
$_namespace = current(explode('\\', $params['__NAMESPACE__']));
// Most generic session namespace.
if(in_array($_namespace, ['Customer', 'Application', null])) {
$_namespace = 'Zend_Auth';
}
$auth->setStorage(new \Zend\Authentication\Storage\Session($_namespace));
This does not create a second cookie, but it does mean I can go to domain.dev/account (customer section) and be able to log in independently of domain.dev/administrator (admin section) which is ultimately what I was attempting to do.

ServiceStack Twitter Auth and Registration

I've got an app that has been running using CredentialsAuthProvider() for a while.
Today, I'd like to add twitter and facebook as options for people to create an account. I've got the scaffolding in place.
//Register all Authentication methods you want to enable for this web app.
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new CredentialsAuthProvider(),
new TwitterAuthProvider(appSettings),
new FacebookAuthProvider(appSettings)
}));
//Provide service for new users to register so they can login with supplied credentials.
Plugins.Add(new CustomRegistrationFeature());
The endpoints /api/auth/twitter and /api/auth/facebook work, and I see that a user session is created by visiting /api/auth once the OAuth process is complete HOWEVER...
No user is created in my UserAuthRepository (OrmLiteAuthRepository). The User Id stored in the session is invalid. Any method decorated with the [Authenticate] attribute causes a 404 (User not found) error to be returned.
I would expect that a user is created with the First/Last/Email obtained from Facebook or Twitter. Am I misunderstanding something?
ServiceStack v4.0.38
A few things to check would be the oauth.CallbackUrl has been set correctly taking into account the multiple providers you have registered. Eg http://localhost/auth/{0}.
Also you should check if your IDbConnectionFactory used with your OrmLiteAuthRepository has also been registered with the IoC container. Eg
var dbFactory = new OrmLiteConnectionFactory(
"~/App_Data/db.sqlite".MapHostAbsolutePath(),
SqliteDialect.Provider);
container.Register<IDbConnectionFactory>(dbFactory);
var authRepo = new OrmLiteAuthRepository(dbFactory);
container.Register<IUserAuthRepository>(authRepo);
authRepo.InitSchema();
I wanted to update this thread to say that I've upgraded to ServiceStack 4.0.42 and this issue has resolved itself.

JSF 2.x HttpSession bean upon login.. proper way to use it?

I've looked at some other threads here and I think I have the general idea of how to use a SessionScoped bean for maintaining a user's logged in state. However, as I am relatively new to JSF 2, I am trying to figure out the best way to use the bean during login and on subsequent pages to render a header/footer (using same page template, but different menus/links depending on login state and non-logged in state).
I have a typical JSF2 login form that calls a backing bean (request scoped) login() method. All of that works, and I am going to tie it in to the container security soon as I have a little more time to work on and figure that part out (realms, roles, etc).
In the old pre-JSF (jsp/struts) days, upon login, I'd add an object, usually a user ID Long value that would be easy to replicate across a cluster of sessions and restore a full user object from. This kept the httpsession data minimal (one Long value per user), and regardless of what server a user was routed, I could determine they were logged in and pull up their user object and go from there.
With JSF, I am not sure the right way to do this. I have a SessionScoped bean with a Long userid property. Upon the login() method succeeding, I use the ExternalContext to add the attribute of the SessionScoped object, something like:
User user = loginBean.login(username, password);
Session session = new Session();
session.setUserid(user.getId());
externalContext.getSessionMap().put("usersession", session);
externalContext.redirect(originalURL);
The Session is the SessionScoped bean, and it's CDI name is usersession. I hope that is the right way to stick the bean into the HttpSession so it can be used on pages, etc with EL.
The first thing I am not sure of is because the bean is SessionScoped, do I need to put it into the session after creating it in the above code? Or is that done automatically upon creation for me since it's scoped as session?
The second question is.. being picky that I am, I don't want a Session object in the session until the user logs in, even if the userid is null. So on a xhtml page, if I have something like:
<h:panelGroup render="#{usersession.loggedin}"...>
Will that create and put the Session bean into the session the first page that uses that? Or will that Session object not be put into the HttpSession until I do so with my code above? My guess is, if it gets put into the session upon creation, then the use of it on any page will create it and stick it in the session. I am less bothered by this..the object with just the Long property is very little memory use per user on the system, but like I said, I am being picky and more so wanted to understand exactly when a SessionScoped object gets stored into the session.
Thanks.
The first thing I am not sure of is because the bean is SessionScoped, do I need to put it into the session after creating it in the above code? Or is that done automatically upon creation for me since it's scoped as session?
The managed bean is autocreated in the given scope if referenced for the first time in EL by #{beanName} while it's not in the scope yet. So, no, you don't need to do it yourself. Just inject it as managed property in your login bean.
#ManagedProperty("#{usersession}")
private Session session;
// ...
User user = loginBean.login(username, password);
session.setUserid(user.getId());
externalContext.redirect(originalURL);
Will that create and put the Session bean into the session the first page that uses that? Or will that Session object not be put into the HttpSession until I do so with my code above?
It will do that once you reference it for the first time in EL by #{beanName}.
Unrelated to the concrete question, another way is
User user = loginBean.login(username, password);
externalContext.getSessionMap().put("user", user);
externalContext.redirect(originalURL);
and check for the logged-in user as follows
<h:panelGroup rendered="#{not empty user}">
See also:
Performing user authentication in Java EE / JSF using j_security_check

How configure Nhibernate to not save object in current session

I have three entites: Users, Roles and Permissions.
There two controllers: UserController and RolePermissionController. All controller wrapped by Nhibernate Session.
When I create fill Role Permissions, User doesn't exist. So I storage my new Permission object in the ASP.MVC session. I wants to save new Role with permission when I`ll create User in the UserController.
But when I filled new Role with exist Permission (I got then from DB by Nhibernate) and went to the User Controller New object Role created, without call Session.SaveOrUpdate or any other methods.
I tried to use Evict after fill my new role with exist permissions:
Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<ISession>().Evict(newRole);
But it didn't help.
So I want to say to Nhibernate - don't save entity on this transaction (RolePermissionController) - and save as connected to User object entities in the UserController.
This doesn't answer your question directly, but it still might be a solution - how about collecting all the information through a ViewModel, so that you end up with a single controller action that takes the information from the ViewModel, creates the Role and the User at the same time (i.e. during the same request), and no need for messy session stuff.
Maybe not the answer you were looking for, but I've done something similar this way, and it works just fine.

Implementing autologin for ASP.NET MVC

I've been trying to get membership working in ASP.NET MVC. There are some pages that require authentication. Others that can have guests and authorised members. Much like StackOverflow. They can do things anonymously or as a registered user.
We also have a custom database schema of handling members (not the default ASP.NET Membership way). So I'd be looking at writing my own Membership/Principal code. So far its working well, BUT I'm having trouble with sessions expiring and being able to implement the 'Remember me' functionality.
I use FormsAuthentication.SetAuthCookie(username, rememberMe) to set the forms cookie, but say the user leaves the machine for 20mins or IIS recycles my session dies and I get a very inconsistent user state.
Where do I catch the 'Remember me' cookie and how do I handle the user logging in again? Essentially do I store the username and password and then look for the cookie in Application_BeginRequest or something?
If I read you right, it seems like you are expecting ASP.NET to detect the persistent auth cookie and re-establish that user's last session state. It doesn't work that way: the authentication cookie and asp.net session are two independent things, so indeed you will have instances where a user goes back to the site and passes authentication via a persistent AuthCookie, but has brand new (empty) session data.
Assuming the AuthCookie is being set properly, you can detect that the user is authenticated with User.Identity.IsAuthenticated which is not affected by IIS recycles or session expiring. The username is exposed in User.Identity.Name.
If you need to re-initialize some Session data when a user returns to the site you'll have to do that manually. If this is really what you're asking, then it's hard to answer without knowing more about your app, but consider the Session_Start and Session_End events in the global.asax. Alternatively you can just null-check a session object and re-populate whenever it's empty (after session does expire), eg:
//get some user info from session or db if session is null
string preferredName;
if (User.Identity.IsAuthenticated)
{
object o = Session["preferredName"];
if (o == null)
{
preferredName = repository.GetUser(User.Identity.Name).PreferredName;
Session["preferredName"] = preferredName; //save to session so this isn't necessary next time
}
else
{
preferredName = (string)o;
}
}
else
{
preferredName = "anon";
}

Resources