Spring security : auto login issue - spring

i am trying to auto login user after signup. Here is code for auto login
private boolean autoLogin(HttpServletRequest request, User user) {
SimpleGrantedAuthority auth = new SimpleGrantedAuthority("ADMIN");
Collection<SimpleGrantedAuthority> authorities = new HashSet<SimpleGrantedAuthority>();
authorities.add(auth);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
user.getEmail(), user.getPassword(), authorities);
token.setDetails(new WebAuthenticationDetails(request));
authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(token);
return true;
}
and inside an interceptor that check logged in user code is
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Problem is when i debug the code (after auto login) the principal object has logged in user's email address instead of UserDetails object.
Things working fine when i log in useing spring security login form.

You're missing re-assigning the return from AuthenticationManager.authenticate().
This line:
authenticationManager.authenticate(token);
should be:
token = authenticationManager.authenticate(token);
That should fix things.

Related

Extending a Jhipster JWT (Spring) monolith application to support impersonation

I have generated a jhipster angular/java application that is using JWT authentication.
I now want to extend the application to support impersonation.
I am interested in achieving the following:
Impersonation by admin: Allowing the admin user to login as any other user
Impersonation granted to user: Allowing another user that has been granted the right to impersonate a user (granted by the user itself) to login as that other user.
Audit - recording changes (audit function) - the audit trail must be able to distinguish between the actual user and an impersonated user and record this in the audit trail.
I see that Spring supports impersonation but it is unclear to me how I can implement it properly in my Jhipster application given that JWT is used. I am not sure if the Spring route is appropriate for JHipster-JWT-Monolith application - I am of the opinion that it not the right approach.
While there are some incomplete information on various other posts, after an extensive search I have been unable to find a post that can provide clear step by step guide on this. If somebody can do that for me it would be greatly appreciated. I expect others would also find such an answer very useful.
Thanks in advance.
Fergal
You just need to add below method in UserJwtController.java
#PostMapping("/authenticate-externalnodes")
public ResponseEntity<JWTToken> authenticateExternalnodes(#Valid #RequestBody LoginVM loginVM) {
// Get Roles for user via username
Set<Authority> authorities = userService.getUserWithAuthoritiesByLogin(loginVM.getUsername()).get()
.getAuthorities();
// Create Granted Authority Rules
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Authority authority : authorities) {
grantedAuthorities.add(new SimpleGrantedAuthority(authority.getName()));
}
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
loginVM.getUsername(), "", grantedAuthorities);
Authentication authentication = authenticationToken;
SecurityContextHolder.getContext().setAuthentication(authentication);
boolean rememberMe = (loginVM.isRememberMe() == null) ? false : loginVM.isRememberMe();
String jwt = tokenProvider.createToken(authentication, rememberMe);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt);
return new ResponseEntity<>(new JWTToken(jwt), httpHeaders, HttpStatus.OK);
}

How to get Original User after Impersonating another user?

I am using Switch user filter given by spring for Impersonating an user.
How can I get the Original user Who is Impersonating in the SwitchUserFilter.
Steps I am doing:
Ex.
1. Log in with User1
2. Impersonting to the User2. (user1 impersonate User2)
3. In Filter I am getting **authentication.getName()** as **User2**
4. While switching back to Original I am getiing **authentication.getName()** as **Null**
Now My Need is I want to get the original user (User1) in the filter at the time of swtichback.
Can it be possible.
Please suggest.
Let me know anyone needs any more inputs. please comment.
Thanks in advance.
This is how you can access the original User :
Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (SwitchUserFilter.ROLE_PREVIOUS_ADMINISTRATOR.equals(grantedAuthority.getAuthority())) {
System.out.println(((SwitchUserGrantedAuthority) grantedAuthority).getSource().getPrincipal());
}
}
add this custom method in UserJwTController in jhipster generated application
#PostMapping("/authenticate-externalnodes")
public ResponseEntity<JWTToken> authenticateExternalnodes(#Valid #RequestBody LoginVM loginVM) {
// Get Roles for user via username
Set<Authority> authorities = userService.getUserWithAuthoritiesByLogin(loginVM.getUsername()).get()
.getAuthorities();
// Create Granted Authority Rules
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Authority authority : authorities) {
grantedAuthorities.add(new SimpleGrantedAuthority(authority.getName()));
}
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
loginVM.getUsername(), "", grantedAuthorities);
Authentication authentication = authenticationToken;
SecurityContextHolder.getContext().setAuthentication(authentication);
boolean rememberMe = (loginVM.isRememberMe() == null) ? false : loginVM.isRememberMe();
String jwt = tokenProvider.createToken(authentication, rememberMe);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt);
return new ResponseEntity<>(new JWTToken(jwt), httpHeaders, HttpStatus.OK);
}

Injecting Logged in User in Spring

Hi I want my user to be logged in via URL which is secured by spring. URL will contan username as well as password. I tried doing it by sending username and password via controller to customAuthenticationManager and then checked in CustomAuthentication Provider and returned UsernamePasswordAuthenticationToken. when I check isauthenticated flag it shows true but when I try to access a secured page it redirects me to the login page. Where am I going wrong ?
Its not the best way to do it but try this:
public void login(HttpServletRequest request, String userName, String password)
{
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(userName, password);
// Authenticate the user
Authentication authentication = authenticationManager.authenticate(authRequest);
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
// Create a new session and add the security context.
HttpSession session = request.getSession(true);
session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext);
}

Spring Security: Set GrantedAuthorities

Is there anyway to set the List<GrantedAuthority> in the Authentication/UserDetailsImpl object? In my application, I have two layers of security, one for logging in (which uses my custom login authenticator, in the class I set the Authentication object using the UsernamePasswordAuthenticationToken) and one for a "challenge question" where the user is prompted to answer a particular question.
What I want to do is add a GrantedAuthority to the current List<GrantedAuthority>, which was created during the login process, after the user answers the challenge question.
Is this possible?
you can do it with following code:
Collection<SimpleGrantedAuthority> oldAuthorities = (Collection<SimpleGrantedAuthority>)SecurityContextHolder.getContext().getAuthentication().getAuthorities();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_ANOTHER");
List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
updatedAuthorities.add(authority);
updatedAuthorities.addAll(oldAuthorities);
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(
SecurityContextHolder.getContext().getAuthentication().getPrincipal(),
SecurityContextHolder.getContext().getAuthentication().getCredentials(),
updatedAuthorities)
);
The UserDetails.getAuthorities() method just returns a Collection<GrantedAuthority> object. You can use the appropriate Collection method to add your new authority to that collection.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
((UserDetails) principal).getAuthorities().add(New GrantedAuthorityImpl("ROLE_FOO"));
}
Selah.

Howto integrate spring-social authentication with spring-security?

I've got a little webapp secured by spring-security using a username/password combo on a sql-db as credentials.
I now want to add facebook/twitter authentication with spring-social. Using the examples I am able to store the users credentials in my db. I'm now working on authenticating the user against his current session on my app using the following piece of code:
public String signIn(String userId, Connection<?> connection, NativeWebRequest request) {
User user = userService.getUserById(Long.parseLong(userId));
user.setPassword(this.passwordEncoder.encodePassword(user.getAccessToken(), this.salt));
this.userService.store(user);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getDisplayName(), user.getAccessToken());
HttpServletRequest req = request.getNativeRequest(HttpServletRequest.class); // generate session if one doesn't exist
token.setDetails(new WebAuthenticationDetails(req));
Authentication authenticatedUser = this.authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
return "/user/dashboard";
}
The authentication works, I am not getting any BadCredential-exceptions. But after being redirected to /user/dashboard I am thrown back to the login.
I am out of ideas, a similar piece of code for authenticating the session is working after a classical signup.
Does anyone have any ideas why this happens or how to debug this?
Thanks very much in advance!
Hendrik
I have similar code that works for me, and also adds "remember me" support:
// lookup by id, which in my case is the login
User user = userService.findByLogin(userId);
// code to populate the user's roles
List<GrantedAuthority> authorities = ...;
// create new instance of my UserDetails implementation
UserDetailsImpl springSecurityUser = new UserDetailsImpl(user, authorities);
// create new Authentication using UserDetails instance, password, and roles
Authentication authentication = new UsernamePasswordAuthenticationToken(springSecurityUser, user.getPassword(), authorities);
// set the Authentication in the SecurityContext
SecurityContextHolder.getContext().setAuthentication(authentication);
// optional: remember-me support (must #Autowire in TokenBasedRememberMeServices)
tokenBasedRememberMeServices.onLoginSuccess(
(HttpServletRequest) request.getNativeRequest(),
(HttpServletResponse) request.getNativeResponse(),
authentication);

Resources