Pulling the userDetails in custom LogoutHandler Spring MVC - spring

In MyLogoutHandler class I do override determineTargetUrl() method, here I am calling MyUserDetials userDetails = (MyUserDetials)userContextManager.getUserDetails(), but userDetails is null.
here is the configuration:
<security:logout
invalidate-session="true"
success-handler-ref="MyLogoutHandler"
logout-url="/auth/logout"/>
I noticed that since invalidate-session="true", it is null? but I like to keep this attribute "true", Can I have any other way to do configure?
My goal is: I need to pull some information from userDetails, to make a webservice call after user clicks logout.
Thank you.

You need create your own LogoutHandler, implement
void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication);
add it implementation to security:logout tag. After get user details from authentication parameter.

I fixed this issue. I created the My Own Handler and did override the:
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {...}
method of *SimpleUrlLogoutSuccessHandler*. Now I am able to get *authentication* object according to my spring configuration.
Thank you.

Related

Is possible ask for an acces token oauth2 just with refresh token in spring security? without basic authentication?

I would like to know if in spring oauth2 is possible get a new pair tokens (access token and refresh token) just using another refresh token, without the basic authentication (without clientId and clientSecret, is there any way?
For exemple:
WITH BASIC AUTH
curl -u clientId:clientSecret -X POST 'http://myapplication.oauth2/accounts/oauth/token?grant_type=refresh_token&client_id=<CLIENT_ID>&refresh_token=' -v
WITHOUT BASIC AUTH
curl -u -X POST 'http://myapplication.oauth2/accounts/oauth/token?grant_type=refresh_token&client_id=<CLIENT_ID>&refresh_token=' -v
I note that sprint BasicAuthenticationFilter in spring uses validation bellow, maybe override this filter and make the authentication just with refresh token.
String header = request.getHeader("Authorization");
if (header == null || !header.toLowerCase().startsWith("basic ")) {
chain.doFilter(request, response);
return;
}
The short answer is no. The class used to manage the Spring Oauth 2 endpoints is the following one:
#FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint
Both requests, I mean, get access token and refresh one use the same endpoint with different parameters. And the method to manage those ones is:
#RequestMapping(
value = {"/oauth/token"},
method = {RequestMethod.POST}
)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, #RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException("There is no client authentication. Try adding an appropriate authentication filter.");
} else {
String clientId = this.getClientId(principal);
...
As you can see, a Principal object is required (in this case provided by the Basic Authentication).
Even, if you configure the security of your project to permit that url without checking authentication, you will achieve to "enter" in above method but you will receive an InsufficientAuthenticationException because no Authentication instance has been provided.
Why custom authentication will not work
1. Create a custom AuthenticationProvider will not work because the method postAccessToken is invoked before. So you will receive an InsufficientAuthenticationException.
2. Create a OncePerRequestFilter and configure it to execute before process the current request:
#Override
protected void configure(HttpSecurity http) throws Exception {
http...
.anyRequest().authenticated()
.and()
.addFilterBefore(myCustomFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(POST, "/accounts/oauth/**");
}
with a code "similar to":
#Component
public class CustomAuthenticationFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
...
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken("existingUser",
"passwordOfExistingUser",
Collections.emptyList()));
...
filterChain.doFilter(request, response);
}
The problem with this approach is the principal in TokenEndpoint comes from the HttpServletRequest not from Spring context, as you can see debugging BasicAuthenticationFilter class.
In your custom filter you can try, using reflection, set a value in userPrincipal property but, as you can verify, request has several "internal request properties" and that could be a "too tricky option".
In summary, Oauth standard needs user/pass to access to the resources, if you want to workaround in almost of provided endpoints maybe that project is not what you are looking for.
Workaround to include your own object in Spring Principal
I do not recommend that but if you still want to go ahead with this approach, there is a way to include your own value inside the principal parameter received by TokenEndpoint class.
It is important to take into account BasicAuthorizationFilter will be still executed, however you will be able to override the Spring principal object by your own one.
For this, we can reuse the previous CustomAuthenticationFilter but now your have to include the filters you need, I mean, allowed urls, parameters, etc You are going to "open the doors", so be careful about what you allow and not.
The difference in this case is, instead of add the configuration in our class that extends WebSecurityConfigurerAdapter we are going to do it in:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private CustomAuthenticationFilter customAuthenticationFilter;
...
#Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.checkTokenAccess("isAuthenticated()");
security.addTokenEndpointAuthenticationFilter(customAuthenticationFilter);
}
...

Spring-boot Zuul: Passing user ID between microservices

I have a Zuul Gateway proxy, where I check the authorization of token received from the user. Now, when this is request is passed on to other microservices to get the user-specific data, the user information needs to be passed from the gateway to the microservice.
Right now, I've added the user ID in the request header and I'm getting it at respective microservice's controller using API header annotation.
Is this the right way to pass the user information. Is there any other better way?
In case if anyone still facing this issue,
In Zuul Proxy add the header to RequestContext as below:
userId = jwtTokenUtil.getUsernameFromToken(jwtToken);
RequestContext ctx = RequestContext.getCurrentContext();
ctx.addZuulRequestHeader("userId", userId);
And then in the respective microservices write a custom filter and extract the value as below
#Component
public class MyFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String userId = request.getHeaders("userId").nextElement();
logger.info("userId: "+userId);
filterChain.doFilter(request, response);
}
}

Spring controller add attribute to any request

I need to show logged user name on any page. Is it possible to use only 1 method that will be called on any request and will add name attribute to model?
Since you have add spring-security tag in your question,so if you want to show logged user at any page,the best choice is using spring-security.
First,add the below declaration in your jsp page:
<%# taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
Then in your jsp page we can use <sec:authentication property="name"/> to show the logged in user at any page.
Yes and no.
Either you store the username in the Session (setRequestAtrributes) or you create a filterchain which reads the username by the auth-token/authentication. Depending on where you decide which user is logged in.
You can add a Servlet Filter as below which is adding userName into response Header.
#Component
public class MyFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpSession session = httpServletRequest.getSession();
if(session !=null&& session.getAttribute("username")!=null){
httpServletResponse.addHeader("username",httpServletRequest.getSession().getAttribute("username").toString() );
}
}
And use userName from response in your UI.

Call a bean AFTER successful spring security login?

If I have spring security working, how can I have it call a bean to initialize all my user data once it has logged in? I can do a Servlet Filter but it calls that on every request. I want to just call some init code to load some user data into the session after the user logs in.
When the user logs in correctly spring security call an instance of AuthenticationSuccessHandler. What you want to do is create your own bean and use that to perform whatever extra actions you want.
Your class would probably look something like this:
public class YourAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//do whatever you want
super.onAuthenticationSuccess(request, response, authentication);
}
}
Also register your class as a spring bean
<beans:bean id="authenticationSuccessHandler"
class="your.package.YourAuthenticationSuccessHandler"/>
and add it to the form login security configuration as the value of authentication-success-handler-ref

Need to pass value from interceptor to handller in spring

Hey I am new to spring and I need help on below:
I have interceptor with prehandle and posthandle mehtods in it.I want to send some values to handller from interceptor.
suggest any idea.
Thanks.
You can achieve this as:
In your interceptor prehandle method:
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
...
HttpSession session = request.getSession();
session.setAttribute("attributeName", objectYouWantToPassToHandler);
....
}
In your handler handleRequest method:
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
....
HttpSession session = request.getSession();
objectYouWantToPassToHandler objectYouWantToPassToHandler = session.getAttribute("attributeName");
....
}
Actually, your question ins't clear, sorry. Try start from Spring AOP
And, of course, you have to show your code: what you have and what you want to do.

Resources