spring : how to apply role to existing JWT token - java

In SingleSignOn(SSO), i am getting jwt beareer token from my office network when application loads, basically i have written code in the rest web-service to get bearer token from different web-service.
What i want is:
I want to secure some of the rest endpoints in spring? How can i do that!
I don't want to provide login & password forms to re-login. Because already i am calling web-service to get the user-Info and bearer token. It means i am already login, and i am able to print user info.
I have user role table with userId, i just want to apply thoese roles available in the table to logged in User Id.
How can we do thia?
I found this but i am expecting this should not ask to re enter username and password again https://www.ekiras.com/2016/04/authenticate-user-with-custom-user-details-service-in-spring-security.html
https://stackoverflow.com/a/11314388/1684778
similar kind of my problem
https://stackoverflow.com/a/12057327/1684778

There are multiple things to consider here
User authentication: When the user credentials are verified, we mark the user authenticated and register it in SecurityContext
You must be using AuthenticationProvider to authenticate the token received.
Ex:
public class SSOAuthenticationProvider implements AuthenticationProvider {
public Authentication authenticate(Authentication authentication) {
// verified the authentication token
authentication.setAuthenticated(true);
// make the database call, get roles for the user
authentication.setAuthorities(<authorities - discussed below>);
SecurityContextHolder.getContext().setAuthentication(authentication);
return authentication;
}
}
Authorities: Once the user is authenticated, we need to get the granted authorities for the user and set them. For that, we need a custom class to represent the granted authorities.
public class CustomAuthority implements GrantedAuthority {
private String role;
public CustomAuthority(String role) {
this.role = role;
}
#Override
public String getAuthority() {
return role;
}
}
We create these custom authority instances from the roles we receive from the database. So in previous SSOAuthenticationProvider, we do the following
// make the database call, get roles for the user
List<String> roles = <db call to get roles>
authentication.setAuthorities(Collections.unmodifiableCollection(roles.stream().map(CustomAuthority::new).collect(Collectors.toList()));
SecurityContextHolder.getContext().setAuthentication(authentication);
This results in currently authenticated user holding all the roles they are entitled to.
The only pending step is to hardcode the authority/role for each endpoint. Now, when the user authentication process is done and an endpoint verification is performed, Spring looks at the authorities needed for the current endpoint and looks for them in the currently authenticated user. If it's present, the endpoint code gets executed. If not, AccessDeniedException is thrown

Related

Using a JWT token with dropwizard? I already have db auth, but am confused about utilizing tokens

I have the following Authenticator class for DB authentication:
public class DBAuthentication implements Authenticator<BasicCredentials, User> {
private UserDAO userDAO;
public DBAuthentication(UserDAO userDAO) {
this.userDAO = userDAO;
}
#Override
public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException{
return userDAO.findByUsernamePassword(credentials.getUsername(), credentials.getPassword());
}
}
and then when I want to authenticate against a resource, I simply do :
#GET
#Produces(MediaType.TEXT_PLAIN)
#Path("/secured")
#UnitOfWork
public String aliveSecure(#Auth User user)
{
return "working.";
}
Which is a simple, authenticated method - and that works well... However, let's assume I want to have a user sign in, then get a token they can use for future requests, until the token expires... I would ASSUME (and correct me if I am wrong) that I would do something like have a resource, which would take the credentials, then return the token inside a response, for storage on the client end - and that is fine... but if I do that, how would I later authenticate against the token?
You are correct -- You will add an endpoint which issues JWT tokens once authenticated, and then annotate your other protected resources to use JWT authentication.
Check out dropwizard-auth-jwt, which adds JWT support to Dropwizard. There is an example on how to use it in their examples directory on Github.
Specifically look at the SecuredResource class, which can both issue a token as well as validate it.
You can for instance just extend your aliveSecure method to issue a JWT token.
I made an example project available at on Github which uses basic auth to issue tokens, and #Roles with JWTs.

What is the correct way to get the logged user via spring security (angularjs)

After success login, how I can retrieve the logged users in spring RestController?
I use the below method/principle to get the logged user, but it retrieves anonymousUser instead of logged user.
Principal principal = SecurityContextHolder.getContext().getAuthentication();
or
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
You may get the logged in user name from Authentication object. To get the user object, you can then use the username retrieved from the authentication object.
Something like this should work:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
User user = userService.findByUserName(name);
Or better, you can use Principal in your controller as an argument, and let the Spring pass the correct principal object. If the user not logged in, it would be null.
public String hello(Principal principal ) {
String name = principal.getName();
User user = userService.findByUserName(name);
}
Ps: If you are getting anonymous authentication, then the user is not authenticated. SecurityContext returns anonymous authentication is the user is not logged in.
`

OAuth2 - handle password change in Spring Security

I'm implementing OAuth2 for my REST Service (password grant type) with help of Spring security module. I' using postgreSQL as my Token Store. All works fine, but I need to add the possibility to change user password. If user change his password old token should be deleted/forgotten.
I implement this feature using JdbcTokenStore Spring service:
public void updatePassword(User user, String newPassword) {
...
// Update password in database
clearUserTokens(user.getUsername());
}
private void clearUserTokens(String userName) {
Collection<OAuth2AccessToken> tokens = jdbcTokenStore.findTokensByUserName(userName);
tokens.stream().forEach(jdbcTokenStore::removeAccessToken);
}
Is this approach correct? Is there any standard way of handling that kind of situations?

Spring Security: OAuth2 custom filter to validate password expiration error handling

I've been trying to implement OAuth2 password expiration filter and I'm unsure about what the proper way would be to do so. The idea is as follows:
User tries to login.
User gets response with a header containing token if the password is expired.
User get's redirected to password change page using that token (i.e. /password-change/{token}).
He submits his old and new passwords, it gets changed.
Some rest controller retrieves user id by that token and does the rest password changing logic.
User should be redirected back to the initial login page where he logins with his new password (if he would be logged in instantly after the password change, he could navigate through secured pages even if the password would not be changed in background due to some exception, etc.).
So... I set a custom flag in user details for password expiration because I can't use credentialsNonExpired as it gets validated in DaoAuthenticationProvider and thrown as an exception which gets processed as InvalidGrantException which doesn't give me much control. I've figured out that in order to access user details right after it's authentication my filter should be in the inner Spring Security filter chain placed after OAuth2AuthenticationProcessingFilter:
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
...
http.addFilterAfter(new PasswordExpirationFilter(), BasicAuthenticationFilter.class
}
}
Why does my filter get placed after OAuth2AuthenticationProcessingFilter while there's no BasicAuthenticationFilter in the chain? I've digged through Spring Security and OAuth2 documentation and sources and couldn't find the right answer.
If that user's password is expired my filter generates some random string and it saves it to retrieve user details later during the password change request (at least it should be):
public class PasswordExpirationFilter extends OncePerRequestFilter implements Filter, InitializingBean {
private static final String TOKEN_HEADER = ...;
private ExpiredPasswordRepository repo; // gets set in a constructor and is basically holding a concurrent map of tokens
...
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
UserDetails details = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (details.isPasswordExpired) {
String uuid = UUID.randomUUID().toString();
repo.push(uuid, details.getId());
SecurityContextHolder.clearContext();
SecurityContextHolder.getContext().setAuthentication(null);
request.getSession(false).invalidate(); // don't create a new session
response.addHeader(TOKEN_HEADER, uuid);
response.sendError(HttpStatus.SC_PRECONDITION_FAILED, "Credentials have expired");
} else {
filterChain.doFilter(request, response);
}
}
}
Do I have to revoke the OAuth token as well? It gets reused in later requests and I keep getting the last userDetails object and therefore I keep getting the same response from my filter.
Is it even the right place to do all this validation? How should one validate the password for the concrete user and not the OAuth client?
Ok, I think I resolved this issue by revoking the access token via injected TokenStore in my filter (I used BearerTokenExtractor to get the token value) which seems pretty logical in this situtation. I still had no time to figure out, why my filter gets placed after OAuth2AuthenticationProcessingFilter, though.

Spring Security login programmatically (AuthenticationSuccessHandler)

I'm using spring-security 3.2.6 and during testing I programmatically login my users with
public User login(User user) {
logOut();
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
user, user.getPassword(), user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(
authenticationToken);
return user;
}
doing it in that way I notice that isn't going through the AuthenticationSuccessHandler. Is there any way to achieve that?
What you are doing is trying to override the AuthenticationManager. When you want to override AuthentitionSeccessHandler then you need to
Override the AuthenticationFilter.
Authentication filter checks if the incoming request needs authentication, if Yes then calls the Authentication Manager to authenticate the request .
Authentication Manager authenticates request and add it to SecurityContextHolder and returns the Authrntication token which is dy default UsernamePasswordAuthenticationToken.
Filter then checks if there is a SuccessHandler defined. If yes then redirects the request to the AuthenticationSuccessHandler.

Categories

Resources