How to achieve secure REST api along with springboot session and spring security without authentication

1.4k Views Asked by At

Problem: My java springboot application receives JWT token from external system to authenticate a user with their external identity management provider which returns the user details upon success. Once userdetails is received, the backend application must create a redirect url for the external system end user. The redirect url will land the user on my angular application to show the landing page. Here on, all the rest api's should be allowed through an http session. In case the user tries to access the rest api's directly, he should get an Authentication error.

How can we achieve authorization in this case since authentication was not done by my spring boot application. Can we create custom Spring session using spring security and manually put userDetails in the SecurityContext?

1

There are 1 best solutions below

0
On

I am currently dealing JWT tokens obtained from Google. Including Google, pretty much all authorization servers provide rest APIs such as GET /userInfo, where you can carry the JWT token in the request header or in the URL as a GET parameter, and then verify if the JWT token is valid, non-expired, etc.

Because verifying a JWT token is usually stateless, these APIs generally come with a generous limit and you can call them as many times as you need.

I assume that you have Spring security integrated and then you can add a filter. In this way, every request has to be verified for its token in the header.


@Service
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
       String header = request.getHeader("Authorization");
            RestTemplate restTemplate = new RestTemplate(); // If you use Google SDK, xxx SDK, you do not have to use restTemplate 
            String userInfoUrl = "https://example.com/api/userInfo";

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", header);

            HttpEntity entity = new HttpEntity(headers);

            ResponseEntity<String> response = restTemplate.exchange(
                    userInfoUrl, HttpMethod.GET, entity, String.class, param);

            User user = response.getBody(); // Get your response and figure out if the Token is valid.

             // If the token is valid? Check it here....

                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authentication);
            
        } catch (Exception ex) {
            logger.error("Could not set user authentication in security context", ex);
        }

        filterChain.doFilter(request, response);
    }
}