Spring Security authentication/authorization via REST endpoint
Asked Answered
P

2

11

In my Spring Boot application with RESTful webservices I have configured Spring Security together with Spring Social and SpringSocialConfigurer.

Right now I have two ways of authentication/authorization - via username/password and via social networks for example like Twitter.

In order to implement authentication/authorization via my own RESTful endpoint in my Spring MVC REST controller I have added following method:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public Authentication login(@RequestBody LoginUserRequest userRequest) {
    Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userRequest.getUsername(), userRequest.getPassword()));
    boolean isAuthenticated = isAuthenticated(authentication);
    if (isAuthenticated) {
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }
    return authentication;
}

private boolean isAuthenticated(Authentication authentication) {
    return authentication != null && !(authentication instanceof AnonymousAuthenticationToken) && authentication.isAuthenticated();
}

but I'm not sure what exactly must be returned to client after successfull /login endpoint call. I think returning of full authentication object is redundant.

What should be returned to client in case of successfull authentication ?

Could you please tell me how to correctly implement this login method ?

Also, in case of RESTfull login I'll have UsernamePasswordAuthenticationToken and in case of login through Twitter I'll have SocialAuthenticationToken Is it okay to have different tokens in a same application ?

Priesthood answered 22/4, 2015 at 10:1 Comment(0)
C
8

You can configure what to return on successful authentication by overriding methods in SimpleUrlAuthenticationSuccessHandler


public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    public CustomAuthenticationSuccessHandler() {
        super();
        setRedirectStrategy(new NoRedirectStrategy());
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {

        super.onAuthenticationSuccess(request, response, authentication);
        ObjectMapper mapper = new ObjectMapper();

        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().print(mapper.writeValueAsString(objectToBereturned);
        response.getWriter().flush();
    }

    protected class NoRedirectStrategy implements RedirectStrategy {

        @Override
        public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
                throws IOException {
            // any redirect if required. leave the implementation black if not needed
        }

    }
}

Additionally you can also handle the failure response:


public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }
}
Crellen answered 16/3, 2017 at 10:54 Comment(3)
Thanks for your answer. This is exactly what I already use for my current application.Priesthood
It's seems that NoRedirectStrategy is not available in Spring Boot 2.x, where I can take it from?Slaby
@LeonidDashko NoRedirectStrategy is not provided by spring. It is my implementation of RedirectStrategy interface. You can find the same in above code. There is a protected NoRedirectStrategy class that implements RedirectStrategy interface. However if you don't want to use it you can use the DefaultRedirectStrategy provided by spring.Crellen
C
1

Restful calls should always return response code. In your case it should be just 200 OK. On failure 401 Unauthorized. Having different tokens is absolutely fine, you cannot use the same anyway.

I personally would prefer to handle login endpoints through Spring Security filters and not controllers as you can control the flow better.

Channa answered 3/5, 2015 at 11:25 Comment(2)
Is there any documentation or guidance on how to handle the login endpoint through a Spring Security filter?Rusert
There are for sure. You could search for Spring Security Java config examples and look for custom authentication entry point implementations, or login filters. Here would be one example: blog.jdriven.com/2014/10/…Channa

© 2022 - 2024 — McMap. All rights reserved.