How to programmatically change current Principal in Spring Security? - java

How do I change my the current user that is currently login in the application?
Here's the code that I use to switch the current user to it's another account/relative account.
User user = userService.getUser(dependentId);
String access_token = authorizationToken.replace("Bearer","").trim();
if(SecurityContextHolder.getContext().getAuthentication() != null) {
User relative = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
for(Role role: relative.getRoles()) {
if(role.getName().equals("PATIENT")) {
OAuth2Authentication oauth2 = defaultTokenServices.loadAuthentication(access_token);
User o3 =(User)SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
Authentication authentication = new UsernamePasswordAuthenticationToken(user,
user.getPassword()
,user.getAuthorities());
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oauth2.getOAuth2Request(),authentication);
SecurityContextHolder.getContext().setAuthentication(oAuth2Authentication);
User o5 = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
break;
}
}
I ran the code on my debugger, I am expecting o5 to be a different object from o3 but they are still the same

Related

Does spring security context persist across REST/SOAP calls?

Do Spring security context persist while calling rest/soap services from Client. I have client application which sets authentication using SecurityContextHolder.getContext().setAuthentication(). Client application makes rest/soap calls where I have to get context.
//Setting security context in client application:
User contextUser = new User(username, enc_password, true, true, true, true,grantedAuthorities, null);
authentication = new UsernamePasswordAuthenticationToken(contextUser, username,grantedAuthorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
// on server side
// I want to get following authentication on server side to get logged in user
Authentication auth=SecurityContextHolder.getContext().getAuthentication();
User user= null;
if (auth != null && !(auth instanceof AnonymousAuthenticationToken)) {
// userDetails = auth.getPrincipal()
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = null;
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
user = (UserDetails) principal;
} else {
username = principal.toString();
}
}
To access username on server side, after REST/SOAP API calls are made, you can do it by adding username in each request's header, before making API call.
Intercept each request on the server-side by using Spring Interceptors, you can create interceptor class by implementing a HandlerInterceptorAdapter interface.
For more information about interceptors.

Safest way to store an authentication token

I have my custom AuthenticationProvider which call a third party SSO to authenticate a user. If a user is valid I get an authentication token from the SSO service. I have to keep this token during the session for another services which will require this authentication token to verify the user has a valid session.
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String id = authentication.getName();
String password = authentication.getCredentials().toString();
JsonObject response = ssoClient.login(id, password);
JsonObject session = response.getJsonObject("session");
JsonObject user = session.getJsonObject("user");
String email = user.getString("email");
String username = user.getString("username");
String fullname = user.getString("fullname");
String auth_token = session.getString("auth_token");
List<GrantedAuthority> grantedAuths = null;
return new CustomAuthenticationToken(username, auth_token, email,
fullname, grantedAuths);
}
I have extended from AbstractAuthenticationToken to create a custom CustomAuthenticationToken to store this token and another information. Should I sign this token with something like itsdangeous (but in java) or encrypt it? Or should I store the authentication token in any other place? Thanks!

How to modify dynamically the roles of the logged user in Spring Security 4?

i'm trying to update the roles associated with the current logged user without log out, but it's not working as i wish.
Here is my code :
PreAuthenticatedAuthenticationToken authtoken_orig = (PreAuthenticatedAuthenticationToken) SecurityContextHolder
.getContext().getAuthentication();
Collection<? extends GrantedAuthority> Authorities_orig = authtoken_orig.getAuthorities();
ArrayList<SimpleGrantedAuthority> Authorities_new = new ArrayList<SimpleGrantedAuthority>();
for (GrantedAuthority sga : Authorities_orig) {
SimpleGrantedAuthority tmpsga = (SimpleGrantedAuthority) sga;
if (tmpsga.getAuthority().compareTo("ROLE_UNKNOWN") != 0
&& tmpsga.getAuthority().compareTo("ROLE_SIGNER") != 0) {
Authorities_new.add(tmpsga);
}
}
SimpleGrantedAuthority role_signer_auth = new SimpleGrantedAuthority("ROLE_SIGNER");
Authorities_new.add(role_signer_auth);
PreAuthenticatedAuthenticationToken authtoken_new = new PreAuthenticatedAuthenticationToken(
authtoken_orig.getPrincipal(), authtoken_orig.getCredentials(), Authorities_new);
SecurityContextHolder.clearContext();
SecurityContextHolder.createEmptyContext().setAuthentication(authtoken_new);
Please could you advice ?
Thanks in advance
David L.
First eval Granted Authority for the logged-in user like:
GrantedAuthority grantedAuthority = getNextRoleToAssign(context.getUserDetails());
Now, then initialiaze UsernamePasswordAuthenticationToken by using below code:
Authentication auth = new UsernamePasswordAuthenticationToken(authorisedUser, passowrd,Collections<GrantedAuthorities>);
Finally, set this Authentication into the Security context for the current User as mentioned below:
SecurityContextHolder.getContext().setAuthentication(auth);
Your method works, my roles assumption was erroneously based on the principal authorities and not on the authentication authorities. The result of
sc.getAuthentication().getAuthorities()
is not the same as
((UserDetails)sc.getAuthentication().getPrincipal()).getAuthorities()
(Where sc is the securitycontext)

How to log in a user using Spring security manually?

I created a user with a fake username and a password. I tried to log in this user with java code. I can obtain username correctly by
SecurityContextHolder.getContext().getAuthentication().getName()
However, the jsp tag
<sec:authorize access="!isAuthenticated()">
is still false. And <sec:authentication property="name" /> is anonymousUser. How can I fix it? Thanks
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
GrantedAuthority grantedAuthority = new GrantedAuthority() {
//anonymous inner type
public String getAuthority() {
return "ROLE_USER";
}
};
grantedAuthorities.add(grantedAuthority);
User tempUser = new User(username, passwd, true, true, true, true, grantedAuthorities);
Authentication authentication = new UsernamePasswordAuthenticationToken(tempUser, "", grantedAuthorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
HttpSession session = httpServletRequest.getSession();
User authUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
session.setAttribute("username", authUser.getUsername());
session.setAttribute("authorities", authentication.getAuthorities());

How can I save information for current user in Spring & Hibernate?

I have a User table and a UserInfo table which keeps the personal information of the user. What I am trying to do is adding personel information after log in. There is OneToOne relationship between tables with userId column so I defined it like this :
UserInfo class :
public class UserInfo {
//...
#OneToOne
#JoinColumn(name="user_id")
private User user;
// ...
}
User class :
public class User implements UserDetails {
// ...
#OneToOne(mappedBy="user", cascade = CascadeType.ALL, fetch=FetchType.LAZY,optional=true)
private UserInfo userInfo;
...
}
After I log in, I want to add some user information to the db for current user. But I don't know how can i save user information in controller? Should I save User object like below? I've searched about it and there is a way to get current user's information:
(User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
But when I try to use it in the controller it just returns null. How can I do such operations (adding pers. info) for logged in user?
#RequestMapping(value = "/show", method = RequestMethod.POST)
public ModelAndView newUser(ModelMap model, Principal principal) {
ModelAndView result = new ModelAndView("home");
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserInfo userinfo = new UserInfo();
userinfo.setPlacesVisit(userinfo.getPlacesVisit());
user.setUserInfo(userinfo);
userService.save(user);
String message = "Userinfo was successfully added.";
result.addObject("message", message);
return result;
}
instead of saving current object update current object. First get current user object in controller after that set UserInfo then update user object in database.
#RequestMapping(value = "/show", method = RequestMethod.POST)
public ModelAndView newUser(ModelMap model, Principal principal) {
String userName=principal.getName(); // username or email using user login
User user=userService.getUserByName(userName); // retrieve current user information
UserInfo userinfo = new UserInfo(); // create userinfor object
userinfo.setPlacesVisit(userinfo.getPlacesVisit());
user.setUserInfo(userinfo); // set userinfo to user
userService.update(user); // update user
String message = "Userinfo was successfully added.";
result.addObject("message", message);
return result;
}
You can retrieve to user with the Principal parameter :
public ModelAndView newUser(ModelMap model, Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
}
SecurityContextHolder is a part of Spring Security. If you want to use this component, you have to set up Spring Security for the log in of your application to be able to retrieve, in your REST controller, the current user (javax.security.Principal)
Spring Security Documentation
You can use session to save session attributes. In spring, you can access session using
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession();
You can save your logged user in session:
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
request.getSession().setAttribute("key", user);
and if you want get currently logged user, just:
(User) user = ((HttpServletRequest) request).getSession().getAttribute("key")
This example is in JSF, but I am sure that is also possible without JSF

Categories