I'm using Spring Boot and Spring Security. I have 2 apps. They works in couple. And when I want to logout from one, it should also logout from another. I use default logout flow. On application A I click logout link:
<logout invalidate-session="true" delete-cookies="JSESSIONID" logout-success-url="/app-b-logout" />
#RequestMapping("/app-b-logout")
public RedirectView appB_Logout() {
return new RedirectView("http://appB/logout");
}
On application B I have following settings:
.logout().permitAll().logoutUrl("/logout")
And logout success handler:
public class MyLogoutSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler
implements LogoutSuccessHandler {
#Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
System.out.println(authentication == null); // MAGIC HERE
}
}
And in line System.out.println(authentication == null); I have different results. If I redirect from application A, authentication is null, when I click LOGOUT button on app B (using post form), I have authentication object.
But in both cases user is logged out in result. But I need to do some stuff with authentication object. How to make redirect on app A to make a POST request or just how to get this authentication when I redirect from app A?
Related
I have an implementation of AuthenticationSuccessHandler that catches the request after user is successfully logged in. So when processing is finished inside a handler, I want to redirect a user to the page that he first desired to go, before he was redirected to the login page, and not to some hardcoded page. Is this possible?
This is how my handler implementation looks like:
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
Util.setUserdata(userBean, authentication, request);
proceed(request, response, authentication);
}
To explain the problem more clearly, a short example:
User wants to land to a page app/test/page.html
He gets redirected login page and logs in successfully
Handler method gets invoked and I do some logic after which I want to redirect him back to app/test/page.html, but I don't know how to access the URL he wanted to land on before redirection to login page.
Spring security's ExceptionTranslationFilter actually stores the request in session before redirecting to login.
ExceptionTranslationFilter.java
And then it has SavedRequestAwareAuthenticationSuccessHandler which is a AuthenticationSuccessHandler that retrieves and forwards to it.
SavedRequestAwareAuthenticationSuccessHandler.java
You don't need to use that SavedRequestAwareAuthenticationSuccessHandler directly if you have some customization. You can get the previous url directly from session like session.getAttribute(""SPRING_SECURITY_SAVED_REQUEST") as well and it has url and method etc so you can do the redirect yourself. You will have to cast it to SavedRequest before you can the url etc if you are going this route
I'm developing a system with 3 smaller projects, which are as follows:
a client
a ressource server
a authentication server
The authentication server has a register and a login page. The resource server is secured by the authentication server.
From the client I want to access the resource via REST API. The client is calling the resource server via OAuth2RestTemplate from Spring to access the resource. I managed to access the resource, after I authenticated myself.
Now to the problem. At the client I need to know the current user to display the the username and enabling the user to change his profile.
I tried to access the principal of the user via spring security with
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
but it just returned null.
So my question is: Is there a way to get the current logged in user with the OAuth2RestTemplate?
Edit:
So I decided to change the plan to implement a link in my authentication server, which returns the user information. The problem is, when I want to talk the authentication server via OAuth2RestTemplatethe authentication server just returns the login page. Everything works fine, when I call the page from browser or when I want to talk to the resource server via OAuth2RestTemplate.
Set a TokenEnhancer to your AuthorizationServerEndpointsConfigurer in Authorization server. You can add User information to the token as additional info map.
Here is a sample implementation of a custom TokenEnhancer,
public class CustomTokenEnhancer implements TokenEnhancer {
#Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
final Map<String, Object> additionalInfo = new HashMap<String, Object>();
UserDetails user = (UserDetails) authentication.getPrincipal();
additionalInfo.put("<custom_user_info>", user.getUsername());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
In your Authorization server,
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenEnhancer(new CustomTokenEnhancer());
}
Add authentication object to security context holder after successfull authentication, by overriding method of class AbstractAuthenticationProcessingFilter
public void successfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authentication) throws IOException, ServletException
{
// Add the authentication to the Security context
SecurityContextHolder
.getContext()
.setAuthentication(authentication);
}
I am working on a spring MVC application And we are using Spring Security.
Now I have a requirement that as soon I enter into the application, a pop up should be displayed. So the application might enter directly into home page or to his profile page or to any other flow in the application. But I need to show the pop up irrespective of where the user enters.
How do I achieve this using Spring security or any other alternative please?
I have tried:
config.xml:
<bean id="popUpFilter" class="myPackage.security.popUpClass" />
<security:http entry-point-ref="myAppAuthEntryPoint" use-expressions="true">
.............
<security:custom-filter after="LOGIN_FILTER" ref="popUpFilter"/>
</security:http>
And My Code:
public class popUpClass implements AuthenticationSuccessHandler {
private static final Logger log = LoggerFactory.getLogger(popUpClass.class);
#Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
//do some logic here if you want something to be done whenever
//the user successfully logs in.
log.debug("Entered into customfilter");
HttpSession session = httpServletRequest.getSession();
User user = SecurityClass.getUserDetails();
session.setAttribute("id", user.ID());
session.setAttribute("state", user.State());
//set our response to OK status
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
//since we have created our custom success handler, its up to us to where
//we will redirect the user after successfully login
httpServletResponse.sendRedirect("home");
}
}
NOTE: Popup should appear only once after the user log in.
I'm using Spring Security's ability to auto login by unauthenticated request, when it looks at request url and determines whether user is using correct token or no, then do auto login on success and show message on failure:
public class LinkRememberMeService implements RememberMeServices, LogoutHandler
{
#Autowired
private UserAccountProvider userAccountProvider;
#Override
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response)
{
//if ok - return authentication object
//if not ok - retun null then spring redirects to default intercept-url
//but instead of retuning null i need to render view with error message for this case
}
.....
}
autoLogin can return authentication object or null, when object is returned (token is ok) user is automatically logged in, that's fine. However in case of bad token you have only one option to return null, and Spring redirects to default entry url (ex. '/login').
In case of bad token i want to either render thymeleaf template or redirect to failure url, but i can't find a way to make it work.
I have implemented a login page with Java and Spring mvc.
"index.html"
THe problem now is that you can easily get around it by just calling /person.html and you´re into the application.
How can I prevent this without having to use Spring Security?
Very basic answer.
Create an interceptor class that extends HandlerInterceptorAdapter. In the preHandle method check if the user exists in session and return true only if the user exists in session.
public class AuthenticationCheckInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//Check if user exists in session.
//If no, redirect to login page using response.sendRedirect() and return false
//If yes, return true
}
}
Apply this interceptor to all URLs which require you to be logged-in.
A simple example is at http://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/