Spring UserDetails and my User implementation in session - spring

I'm developing my Spring application with the support of Security Model.
I configured everything and it seems to work fine, but I have a conceptual question.
In my controller I can retrieve the User Details generated by Spring like this:
UserDetails userDetails = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Now, should I put this user in the Http session or it's useless?
And also, should I retrieve my User implementation on the basis of the UserDetails object and put it in the session?
What is the right way of thinking with security? I would need my user implementation to retrieve some information but I don't know to keep both around.

http://docs.spring.io/spring-security/site/docs/3.0.x/reference/technical-overview.html#d4e731 in this docks 5.3.1 you can see example.
Something like this:
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);

Related

Is there any advantage using UserDetailsService of Spring Security, when setting membership with JWT?

I'm applying JWT to authenticate the requests. Parsing and Validating works in my Spring Cloud Gateway.
I made a custom filter on SecurityWebFilterChain, which parse and validate the JWT in request header.
I will add this custom filter to ServerHttpSecurity using ServerHttpSecurity.addFilterBefore(myCustomJwtRequestFilter, UsernamePasswordAuthenticationFilter.class).
I want to use
SecurityContextHolder.getContext().setAuthentication(authentication) of Spring Security to authenticate the request.
I found that most of examples of it use UserDetails to make Authentication class.
Most of examples I found use UsernamePasswordAuthenticationToken, and I found that it requires UserDetails. To build UserDetails, it essentially requires username, password, roles.
But in my case, I do not want to validate my jwt with User DB every time I got requests. Also, I do not need the password of user since I will not validate it once I generated Token. I want to use only Username and Roles in JWT payload itself.
In summary, I want to make Authentication class only with username and roles and set it authenticated if parsed jwt is validated with my custom method.
It works well with custom userDetails:
UserDetails userDetails = User.builder().username(String.valueOf(parsedInfo.get("username")))
.authorities(parsedInfo.get("roles")).password("dummypassword").build();
But I have to set Dummy password into it, which I do not need.
I think my solution is not properly applying spring security.
But if I won't use UserDetails, is there benefit to use spring security?
Is there any better solution for my case?
If you just need to validate the JWT token then you can use Spring AOP for that.
#Aspect
#Component
public class JwtAspect {
#Before("execution(* com.yourpackageName.* (..))")
public void checkJwtToken(JoinPoint joinPoint) {
String jwtTOken = request.getToken();
if (null == jwtToken) {
throw new Exception("Token Not Found. ");
}
parseToken(jwtToken);
joinPoint.proceed();
}
}
If you get the token, parse it and also check the expiry. If above everything works fine, you can proceed your JoinPoint.

How can I get all roles of a user by user id in Spring Security?

Is it possible in Spring Security to get all roles of a user if I only know a username? I am thinking of something like this:
List<String> userRoles=veryCleverObject.getRolesByUsername("user123");
I know how to do this for current user but not for any user. My workaround is I query it with JpaRepository from the db but this is not a good solution for obvious reasons.
I need this in a simple user management modul in my app where I list the users and I would like to show their roles.
How can I do that in Spring Security?
In general: no, as authentication may be made via AuthenticationProvider or even AuthenticationManager which, as a rule, require some credentials along with the username; even more, they require this data to be packed in some Authentication class instance. Usually, you don't have any credentials, only a username, and you don't know how to build that Authentication in a generic way.
But if you only use UserDetailsService-based mechanisms (like JDBC authentication http://www.mkyong.com/spring-security/spring-security-form-login-using-database/ or LDAP authentication https://spring.io/guides/gs/authenticating-ldap/ you could just use that UserDetailsService instance which has the following method:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
It finds UserDetails by username, from which you can get user roles (aka granted authorities).
UserDetailsService may be obtained via dependency injection.

Spring Security login automatically after user creation

I have successfully used spring security to login users. But the issue is, right now on my web page, when a new user is created, he/she has to again go back to sign in page to login which of course uses spring security. Is there a way to login the user automatically using Spring Security as soon as a new user is created?
do this
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken (userDetails, password2, userDetails.getAuthorities());
authenticationManager.authenticate(auth);
if(auth.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(auth);
}
I have never done it, but i think you should do what it is described in the doc.
Once the request has been authenticated, the Authentication will
usually be stored in a thread-local SecurityContext managed by the
SecurityContextHolder by the authentication mechanism which is being
used. An explicit authentication can be achieved, without using one of
Spring Security's authentication mechanisms, by creating an
Authentication instance and using the code:
SecurityContextHolder.getContext().setAuthentication(anAuthentication);
Note that unless the Authentication has the authenticated property set to true, it will still be authenticated by any security interceptor (for method or web invocations) which encounters it.

Spring Security user account registration, creation and management

I've been looking into using Spring Security for the authentication/authorization of my web application (this will be JDBC based).
However, a core component seems to be left out from my perspective. How do I register/create new users? Is there an out of the box API for that?
Do i need to write user registration and management from scratch?
Things i need to do include:
- Registering a new user
- Resetting passwords
- Emailing a user to activate their account
- Emailing a user to reset their account.
Thank you in advance.
I use Spring Security on my project. The framework does not have an API for user creation or registration as you asked. For Spring Security to be generic and usable across multiple frameworks, it can only take you so far before you have to write custom code. You can't really get a more specific answer about a framework or tool to use because at this point you will just use the frameworks you are already using anyway.
If you've set it up to use users and roles in your database, from your data access layer you would create a record in the user table or update a password (preferably stored as a hash) in that record. And as Aravind said, Spring does provide email support.
If you really want to see one way to do it: I'm using Spring MVC, JSP, and Hibernate. I use Spring's form tags in a JSP to bind a new user form to a Person object, and my controller method passes that Person object to my Dao to persist it.
The controller method signature looks like this...
#RequestMapping(value = "/newUser", method = RequestMethod.POST)
public ModelAndView createNewUser(final #Valid #ModelAttribute Person user,
final BindingResult result,
final SessionStatus status,
final #RequestParam(value = "unencodedPassword", required = true) String password) {
...
user.getRoles().add(new Role(user, Role.APPLICATION_ROLE.ROLE_USER));
userDao.createNewUser(user);
...
}
and my PersonDao would use Hibernate to persist the user like so
#Transactional
public void createNewUser(Person user)
{
Session session = sessionFactory.getCurrentSession();
session.save(user);
session.flush();
}
Have a look at my answer here.
"I have implemented a JAVA project for this use case. It is open
source, based on Spring-Security. A release version is on
Maven-Central, so you do not need to compile it, but instead you can
fetch it as maven-dependency to your project!"
<dependency>
<groupId>com.ohadr</groupId>
<artifactId>authentication-flows</artifactId>
<version>1.5.0-RELEASE</version>
</dependency>
As far as I know, Spring Security does not have built in support for new user creation and registration. You will have to manage this yourself. However it does have emailing support. Check here for more on this.

Spring Security: setUserPrincipal manually

In a webapplication with Spring MVC and Spring Security.
Is there a way to set UserPrincipal manually?
I need to switch to another user by an admin part of my webapplication. In my controller, is it possible to setUserPrincipal in the request? To connect as if I were someone else.
Like that: request.setUserPrincipal().getName()
I've done things like this to automatically log people in after registering. It seems that it would do just what you are looking for:
Authentication authentication = new UsernamePasswordAuthenticationToken(
userService.loadUserByUsername(u.getUserName()), null,
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(authentication);
I am grabbing my user from a service. This has to implement the org.springframework.security.core.userdetails.UserDetails interface.
I think this should give you a good idea of what needs doing. I remember it took me a while to piece this together from the docs.

Resources