How to Implement Spring security in Spring MVC application? - java

I'm new to Spring security. I have implemented spring security and have generated the JWT token. Now i need to get the user from the token and set it in the session so that the session for that user maintains until the token expires or logged out. On the other hand i need to access the API's from the controller but the spring security is not allowing to access the API's without the JWT Token. Is it possible to access the API's in my controller by setting the JWT Token globally or in the session for all the requests.
Here is what i tried till now ,
UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(loginRequest.getUserName(), loginRequest.getPassword());
Authentication authentication = this.authenticationManager.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
logger.info("jwt is:"+jwt);
logger.info("authentication:"+authentication.getName());
User user2 = new User();
user2.setUserFirstName(user.getFirstName());
user2.setUserLastName(user.getLastName());
request.getSession().setAttribute("loggedInUser",user2);
request.getSession().setMaxInactiveInterval(60);
request.getSession().setAttribute("menu", MenuUtils.buildMenu(user2));
return "home";
I'm doing this while signing in the user. I'm using Thymeleaf in the frontend.
Thanks for the help in advance !!

You need to add the jwt token to the request headers, when accessing the apis:
headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + jwt);
This allows the api's to read the headers, and check the user and his permissions
You don't need to store the user on the session. The token itself has an expiry date, and it should be send from the browser to the server on every request.

Related

Resolve #RegisteredOAuth2AuthorizedClient with the token obtained outside of spring server of Spring Security 5.2.x

I have a controller method that has an argument OAuth2AuthorizedClient with annotation #RegisteredOAuth2AuthorizedClient.
ResponseEntity<String> getFoo(
#RegisteredOAuth2AuthorizedClient("custom") OAuth2AuthorizedClient client) {
OAuth2AccessToken token = client.getAccessToken();
....
}
In order to resolve this, spring look for OAuth token on OAuth2AuthorizedClientService which actually stores the previously authenticated tokens in memory.
Now, I have a scenario where I obtain JWT token from OAuth server outside of this spring resource server, and trying to authenticate this server by passing token using Authorization header.
But when spring trying to resolve OAuth2AuthorizedClient it is looking for token in-memory with the principle of JWT (which will obviously not found since token is not obtained on this server). Hence send new login redirection for new token.
Overall question would be, is it possible to resolve OAuth2AuthorizedClient with the JWT token (obtained ourside of the server) passed in Authorization header?

Spring Boot: What is the Right Way to Implement Basic Auth with httpheaders

I am consuming a secured Restful Service that grants access through Basic Auth (Username and Password). I have successfully accessed the API service and consumed its API; however, I am still confused as to what is the right way to implement HTTP headers with Basic Auth. I would assume I should authenticate only once, but the way I have constructed my code, it looks like I need to authenticate API with each service method I create.
Should I create a helper method with the authentication and call it on each service?
If you are using Basic Auth you need to always include credentials with your request. In case of OAuth, tokens have expiry. In this case, a token caching mechanism for the duration of a little bit less than the expiration duration would do the trick.
The Basic Auth is a kind of no status authentication. That means the server wouldn't record. Every time you need to provide username and password with your request. Each request is equal to the Server.
For another authentication called OAuth, the first time you request with username and password, the server will return a token to the frontend, which has an expiration period. So, you request every time with the token through the filter, where checks the expiry of the token. If it's not expired, using the same token for requests, otherwise, making a request to get another token.

Using JWT with role based authorization

Background
I am working on a web application using Spring Security and am trying to use JSON Web Tokens for authentication for the first time. The app should restrict access to certain URIs based on user roles. It should provide password change option and enable Admin users to change other users' roles.
In a tutorial I've followed, on each HTTP request to the server the database is hit by CustomUserDetailsService to load the current details of the user which seems heavy on performance:
public class JwtAuthenticationFilter extends OncePerRequestFilter {
//...
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
Long userId = tokenProvider.getUserIdFromJWT(jwt);
UserDetails userDetails = customUserDetailsService.loadUserById(userId);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
//...
}
The author of the tutorial suggests another option:
Note that you could also encode the user's username and role inside JWT claims and create the UserDetails object by parsing those claims from the JWT.
However, this comes at the cost of making it difficult to change user's role as we have no way of discarding issued tokens, without keeping track of them.
Possible solution
I've researched the topic of JWT and came up with the following solution:
Let's store username and role inside JWT claims and set a short token expiration time (using exp claim) - after this period, e.g. 15 minutes, we hit the database to check user's details. If the role has changed, we generate the new token with the new role in payload. If the password has been changed, we require the user to re-authenticate, before generating the new token.
An obvious downside of this solution is that any change in user access rights is effective after the period of expiration time.
Question
Are there any other ways of tackling the issue of handling user details change while using JWTs?
We use JWT tokens with Spring Security and an Angular webapp.
I think your Possible Solution idea is valid. We handle this in a similar manner. Our auth flow looks like:
User signs in at a URL and the response header contains the JWT token
JWT tokens have a short timeout (minutes)
The webapp pings a 'refresh token' service at a shorter interval which detects if a token is valid. If so, the server re-issues a new token including any updated roles for the user, and this is then stored by the webapp for inclusion in future requests to the backend.
Due to the 'refresh' service, if a user's roles change, or if they're banned from the system, they will be automatically notice the new role or be 'locked out' no later than the token expiration time.
This has worked well for us for years now. Our users' roles don't frequently change, and if it's ever desired to have their role immediately updated, they can always sign out / sign back in.
Additional potential solution
However, if it's paramount to have the user's role immediately updated in your system, you could have a Filter in Spring check for the JWT header on each request, and have it do the JWT verification, and add a new, refreshed JWT token on every response.
Then your client can expect to get a revised JWT token on each response back from the server, and use that revised JWT token for each subsequent request.
This would work, but it'd also be relatively expensive if you have a lot of traffic.
It all depends on your use case. Like I said, the 'refresh' service has worked well for us.

Spring security authentication with username only but without password and I need to generate token if login success

I need to generate the token based on authentication without password but we should give username
I used spring security builtin class to get the user
authenticated by knowing only the username.
Here is my code,
Authentication authentication = new UsernamePasswordAuthenticationToken(userObj.getUserId(), "",
grantedAuthorities);

Accessing JWT Token during verification

I am playing with the Spring Cloud OAuth2 implementation using the following examples:
https://github.com/spring-cloud-samples/authserver
https://github.com/spring-cloud-samples/sso
The first is an OAuth server that generates JWT tokens upon authenticating the user. The second is a resource that is being consumed. The resource relays the authentication of the user to authserver as per the OAuth spec.
All seems to work very well, leading me to additional questions:
In the authserver, during authentication, how can I get access to the clientId and clientSecret?
Can I determine which values are used for generating the JWT token?
In SSO, how do I get access to the content of the token (for instance, the principal) once the user is authenticated?
Answer to 3): change the method signature to include:
#AuthenticationPrincipal User principal
This way the authentication credentials will be passed to the controller method called by Spring. The other way is through the security context:
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
As for 2), my guess at this point is that to influence the parameters used to compute the JWT token, one needs to implement a custom AccessTokenConverter. If my understanding is correct the default one called DefaultAccessTokenConverter does not allow for this. I welcome any other opinion on this.

Categories