4

I have a app that is served with spring-boot. I have added some controllers for "api/..."-calls that do different things the angular-frontend needs. How do I secure these urls so that only my frontend can reach examlpe.com/api/... and not every user? I don't want anyone to be able to reach examlpe.com/api/... from their browser but they should be able to reach example.com.

The url example.com/api/userinfo sends back information about the currently logged in user. Only my frontend should be able to make these calls.

I realise that some kind of authentication needs to be implemented for these calls. Do I send some kind of tokens when making calls to the api. What are the best practices?

  • This may be helpful https://cloud.google.com/endpoints/docs/frameworks/python/restricting-api-access-with-api-keys-frameworks – Prabhav Sep 08 '17 at 12:39

4 Answers4

0

This seems to be doable by spring security authentication. While sending the request you will need to pass the authentication parameters, which will be validated by spring-security module and afterwards call will reach to your controller. I haven't tried it out yet.

Check this out: How to secure REST API with Spring Boot and Spring Security?

0

Create two packages or at least two class file to serve, say

  1. FrontController.java serve the html file only
  2. FrontApi.java serve the api data only

Add Spring token based(jwt) security so that without token, no one will be able to access your api from browser. Angular has very good support to add token for each request.

@Controller
@RequestMapping("/")
public class FrontController {

    @RequestMapping(value = "", method = RequestMethod.GET)
    public String getFrontPage(){
        return "/frontPage";
    }
}


@RestController
@RequestMapping("/api/v1/front")
public class FrontApi {

    @RequestMapping(value = "", method = RequestMethod.GET)
    public Data getFrontData(){
        // call service
        // return data
    }
}

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
}

and don't forget to add the security dependency & I skip front end code.

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-security</artifactId>
 </dependency>
maruf571
  • 1,836
  • 2
  • 21
  • 18
0

You can add custom CORSFilter and restring origin of requests by adding the permitted URL in Access-Control-Allow-Origin field to the header. Below is how to achieve that -

public class CORSFilter implements Filter {

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    System.out.println("Filtering on...........................................................");
    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader("Access-Control-Allow-Origin", "permitted URL here");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization, Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers");

    chain.doFilter(req, res);
}

public void init(FilterConfig filterConfig) {}

public void destroy() {}

}

You may modify this filter as your need.

EDIT

The above way is not fully secure as header values can be breached by intruder. Best solution is to use token based authentication. JWT is one of the best option here.

Jignesh M. Khatri
  • 1,407
  • 1
  • 14
  • 22
0

Without much additional research on top of what I already know of Spring Security, one approach you may consider is to utilize Spring Security's role basic authorization.

In a common DAOAuthenticationProvider scenario, ensure that, within your Database, your User Table which acts as a UserDetails child has a 'role' column and that your GrantedAuthorities are returned correctly.

Insert a "user" for your frontend and provide a unique role that you know no user will ever be provided, such as "frontend", for example.

Now, whenever your frontend sends requests to your Spring Boot backend, you can send the request with the user/role created specifically for your frontend in the HTTP Authorization headers. Of course, either make sure you're using HTTPS and/or send the user data within a JWT, or some kind of heavily encrypted token. Additionally, you may not want to send the role itself within the HTTP request and only send the user's id. From there, you can query the DB via that ID and retrieve the role, of course.

Keith
  • 161
  • 1
  • 10