How to reject access in Spring after successful authentication - spring

I'm implementing some REST services in Spring and need to reject, in some cases, a successful login of a user.
I have implemented my UserDetailsService and programmed the loadUserByUsername(String username) method, but, when a user gets correctly authenticated, I need to do another validation and, if it fails, reject the access.
To do so I have implemented a listener to detect correct authentications:
#Component
public class LoginSuccessListener implements ApplicationListener{
#Autowired
LicenseControlService licenseControlService;
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent e){
User user = (User)e.getAuthentication().getPrincipal();
//Here I want to reject the access because of whatever logic
}
I need to be sure to apply the logic which might reject the access when the user gets correctly authorized, that's why I need to put the logic when I receive this event.
Is there any way to do that?

Im posting the solution I have adopted in case someone needs the same behaviour:
What I did was, at the class which implements the UserDetailsService, when returning the User class, instantiate it with a false at the enabled property... that returns a 401 to the requester.
I also implemented a CustomAuthenticationEntryPoint which extends BasicAuthenticationEntryPoint, and with an overriden comence method. That method is called whenever Spring is returning an authentication error, so, in this method, I can query the type of the AuthenticationException and decide and modify the returned status according to it.

Related

Save the Spring Security Context back to session for subsequent use

My SpringBoot application is a packaged software application, to customize it I want to manipulate the authentication object when users first login, and I expect this object would be pushed back to the user's session for subsequent connection.
I managed to use an Around advice to intercept a REST endpoint that will be triggered when first login:
#Around("execution( * com.myproject.CurrentUser.get(..)))"
public ResponseEntity getCurrentUser(ProceedingJoinPoint pjp) throws Exception {
SecurityContextHolder.getContext().setAuthentication(getNewAuthentication());
((ServletRequestAttributes) RequestContextController.currentRequestAttributes())
.getRequest().getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING.SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
ResponseEntity response = (ResponseEntity) pjp.proceed();
return response;
}
The getNewAuthentication() method is confirmed OK, it returns a PreAuthenticatedAuthenticationToken that includes additional authorities.
However in the subsequent REST calls when I check the Security Context object the authentication is still the original one.
May I know what would be the proper way to do this? I need to manipulate the authentication object at the very beginning and make sure the subsequent calls will make use of it.
Any idea?

How can I find which AuthenticationProvider/Filter failed in my SimpleUrlAuthenticationFailureHandler?

(I am using Spring Boot 1.3.5 and Spring Security 4.2.2).
I have multiple custom AbstractAuthenticationProcessingFilters and AuthenticationProviders in my application, and they each can throw different types of exceptions that all should result in a failed authentication. So I wrote a class which implements AuthenticationFailureHandler and implements
onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
to listen for failed authentication attempts.
My question - is it possible within my SimpleUrlAuthenticationFailureHandler to know which AbstractAuthenticationProcessingFilter failed? I'm able to get the specific exception that was thrown since the last parameter is AuthenticationException, but I also need to know the AbstractAuthenticationProcessingFilter that failed to determine how to proceed.
Would it work to wire a separate instance of SimpleUrlAuthenticationFailureHandler for each filter? It might be simpler than one handler that knows everything, e.g.:
MyFirstFilter first = new MyFirstFilter();
first.setAuthenticationFailureHandler
(new SimpleUrlAuthenticationFailureHandler(...));
MySecondFilter second = ...
http
.addFilter(first) ...
If not, you could possibly write something to the request object.
Instead of extending AbstractAuthenticationProcessingFilter, it might work to instead just extend OncePerRequestFilter, which may give you a flexibility that the AAPF template doesn't give you.

How to handle Privilege Escalation in Spring application

We have an application with 3 different user roles as User, Author & Admin. Each access role is having different set of menus and screens.
Issue is even though Menu item is hidden if we capture the admin URL and past it in user login it is opening the page. All action on the page will not work but still we are planning to restrict the page opening as well.
Only way I could see how we can handle is write a condition in each action to validate the access before opening the page. But with this approach we should touch many files, is there any best way to handle this situation.
Our application is written using Spring MVC framework.
Thanks.
You asked:
But with this approach we should touch many files, is there any best
way to handle this situation.
From Spring MVC HandlerInterceptor javadoc:
"Applications can register any number of existing or custom
interceptors for certain groups of handlers, to add common
preprocessing behavior without needing to modify each handler
implementation."
What you may do:
Write a custom HandlerInterceptor which should extend
HandlerInterceptorAdapter.
Override the boolean preHandle() method. This method is invoked just before the handler is invoked. So you can check access of logged in user (maybe from session). You can write a custom response from within this method.
Register the interceptor in your dispatcher-servlet.xml.
For example:
public class AuthInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String uri = request.getRequestURI();
User user = (User) request.getSession().getAttribute("foo"); //for example
if (...) { //check access to this uri, if access fails
response.sendRedirect("/to/some/url");
return false;
}
return true;
}
}
And register this HandlerInterceptor to dispatcher-servlet.xml:
<mvc:interceptors>
<bean class="your.package.AuthInterceptor"/>
</mvc:interceptors>
You can configure this interceptor to be more url-specific. See Spring Reference and Spring javadoc.

How can I extend the parameters of the OAuth2 authorization endpoint?

I'm having some trouble regarding the authorization endpoint of my Spring based OAuth2 provider. I need more information from the client than there is currently possible. This is what I want to achieve:
I need the custom parameter in the authentication process later on. Is there any simple way to extend the default parameters with my custom one or do I need to implement a certain class myself?
Did some research on how the authentication endpoint works in the current Spring code. I found that the Authorization Endpoint uses a method named authorize that takes all the parameter that are being set and converts then into an AuthorizationRequest. While looking further into the AuthorizationRequest class I found that it holds a map with extensions that is being filled throughout the authorization process. But it does not seem to get filled with my custom parameter (as shown above). This is in fact by only looking at the code, so I might be wrong.
Would it be a good idea to extend the AuthorizationEndpoint with my custom implementation or is there a better and cleaner way to do this?
Update #1 (07-10-2015)
The place where I'd like to use the custom parameter is in my own implementation of the AuthenticationProvider. I need to information to be available inside the authenticate method of this class.
Update #2 (07-10-2015)
It seems that the AuthorizationProvider gets called before the AuthorizationEndpoint. This means that the custom parameter is obtained after the class where I need it (so that's too late).
Maybe I can get the referral Url by either extending part of the Spring security classes or by obtaining it in the HTML through JavaScript. Is this a good idea or should I use another approach?
So I managed to fix the problem myself by searching some more on Google.
What you need to do is speak to the HttpSessionRequestCache to get the referral URL. This is how I solved it in my own implementation of the AuthenticationProvider
#Component
public class CustomProvider implements AuthenticationProvider {
#Autowired
private HttpServletRequest httpRequest;
#Autowired
private HttpServletResponse httpResponse;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(httpRequest, httpResponse);
logger.info("Referral URL: " + savedRequest.getRedirectUrl());
logger.info("Parameters: " + savedRequest.getParameterMap().keySet().toString());
}
}
This will print out the URL of the request that was called before heading to the login page of spring security. The second log method prints out the parameters that where found in this URL. This question and answer helped me in creating a solution for my problem.

Spring webSocket - Reject topic subscription based on user rights with IE8 - determineUser() never called

I would like to reject subscription according to user permissions. I found the following solution and it helped for browsers that support websocket:
https://github.com/rstoyanchev/spring-websocket-portfolio/issues/23
the solution is extending DefaultHandshakeHandler and overriding determineUser method.
the issue is - this method is never called when connecting from IE8.
Would appreciate any help. thanks,
It sounds like your question is more about how to associate a user with the session. By default the WebSocket session gets the user from the HttpServletRequest during the handshake (i.e. getPrincipal). The DefaultHandshakeHandler does provide a protected method but that only works for the WebSocket transport. So currently the best way to associate a user with the WebSocket session is to to wrap the HttpServletRequest (e.g. in a Filter) and return the user.
Spring Security 4 adds support for WebSocket message and subscription protection. You can configure it with Java config:
#Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
#Override
protected void configure(MessageSecurityMetadataSourceRegistry messages) {
messages
.destinationMatchers("/app/your.topic").hasRole("ADMIN")
.anyMessage().hasRole("USER");
}
}
This will protect both, subscriptions and messages sent to /app/your.topic with the role ROLE_ADMIN. Another solution would be mapping the subscription in your controller and using the #PreAuthorize annotation:
#PreAuthorize("hasRole('ROLE_ADMIN')")
#SubscribeMapping("/your.topic")
public String notifications() {
...
}

Resources