Spring security 4.2.3, OAUTH 2, /oauth/token endpoint, CORS not working - spring

Angular 5 app needs to login a user. Token request is sent to /oauth/token. The preflight OPTIONS request(sent by Chrome) fails because of CORS.
I tried to follow the examples at Spring Security 4.2 and various questions and responses on Stackoverflow.
Here is my code :
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/fapi/**").authenticated()
.and()
.httpBasic()
.realmName("MY_REALM");
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://example.com"));
configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS"));
configuration.addAllowedHeader("*");
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
............
}
And here is the request from Chrome
General Headers
Request URL: http://api.example.com/oauth/token
Request Method: OPTIONS
Status Code: 401
Remote Address: 127.65.43.21:80
Referrer Policy: no-referrer-when-downgrade
Request headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: authorization
Access-Control-Request-Method: POST
Cache-Control: no-cache
Connection: keep-alive
Host: api.example.com
Origin: http://example.com
Pragma: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Response:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Language: en
Content-Length: 1111
Content-Type: text/html;charset=utf-8
Date: Mon, 07 May 2018 03:23:15 GMT
Expires: 0
Pragma: no-cache
WWW-Authenticate: Basic realm="MY_REALM"
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
And the error in console:
Failed to load http://api.example.com/oauth/token: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://example.com' is therefore not allowed access. The response had HTTP status code 401.

I could not make it work with the CorsFilter provided by Spring.
The work around here helped.
Spring security, cors error when enable Oauth2
The part of final code
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
#WebFilter("/*")
public class SimpleCORSFilter implements Filter {
public SimpleCORSFilter() {
}
#Override
public void init(FilterConfig fc) throws ServletException {
}
#Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter");
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, origin, x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, resp);
}
}
#Override
public void destroy() {
}
}
In the security configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/oauth/token");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
//.cors().and()
.csrf().disable()
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/fapi/**").authenticated()
.and()
.httpBasic()
.realmName("MY_REALM");
}
/*
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://example.com"));
configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS"));
configuration.addAllowedHeader("*");
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}*/
............
}
I am still waiting for an example that makes it work with Spring Security's CorsFilter.

Instead of what you have done, write a custom cors filter like the following
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN);
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
And modify your configure(HttpSecurity http) override to
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.and()
.csrf().disable()
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/fapi/**").authenticated()
.and()
.httpBasic()
.realmName("MY_REALM");
}

Related

Spring Authorization Server 0.3.1 CORS issue

i created an authorization server using spring-auth-server 0.3.1, and implemented the Authorization code workflow, my issue is that when my front end -springdoc- reaches the last step i get a 401 and this is what's logged into browser console :
Access to fetch at 'http://authorization-server:8080/oauth2/token' from origin 'http://client:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
i'm using spring boot 2.6.12 and here is my CORS configuration for authorization server (also copy pasted it to the client in case ):
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration {
private final Set<String> allowedOrigins;
#Autowired
public WebSecurityConfiguration(
#Value("${spring.security.cors.allowed-origins:*}") List<String> allowedOrigins) {
this.allowedOrigins = new LinkedHashSet<>(allowedOrigins);
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.cors().configurationSource(corsConfigurationSource())
.and()
.csrf().disable() // without session cookies we do not need this anymore
.authorizeRequests().anyRequest().permitAll();
return http.build();
}
private CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
boolean useAllowedOriginPatterns = allowedOrigins.isEmpty() || allowedOrigins.contains("*");
if (useAllowedOriginPatterns) {
configuration.setAllowedOriginPatterns(Collections.singletonList(CorsConfiguration.ALL));
} else {
configuration.setAllowedOrigins(new ArrayList<>(allowedOrigins));
}
configuration.setAllowedMethods(Collections.singletonList(CorsConfiguration.ALL));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Collections.singletonList(CorsConfiguration.ALL));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
and here are my security filter chain for the Auth server :
#Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
return http.formLogin(Customizer.withDefaults()).build();
}
#Bean
#Order(2)
public SecurityFilterChain standardSecurityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
Any idea on what i'm missing ?
If your backend and your app are not running on the same address your browser does normally not allow you to call your backend. This is intended to be a security feature.
To allow your browser to call your api add the Access-Control-**** headers to your backend response (when answering from Spring).
please add the below line in your header
Access-Control-Allow-Origin: *
here is an tutorial also, please visit here on spring.io
i solved it by dropping the corsconfiguration from filter chain bean and creating a filter instead.
'''
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {
private final Set<String> allowedOrigins;
#Autowired
public SimpleCORSFilter(#Value("${spring.security.cors.allowed-origins:*}") Set<String> allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}
#Override
public void init(FilterConfig fc) throws ServletException {
}
#Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
String origin = request.getHeader("referer");
if(origin != null ){
Optional<String> first = allowedOrigins.stream().filter(origin::startsWith).findFirst();
first.ifPresent(s -> response.setHeader("Access-Control-Allow-Origin", s));
}
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, resp);
}
}
#Override
public void destroy() {
}
}
'''

Spring security basic authentication configuration

I've been trying to follow this tutorial :
https://www.baeldung.com/spring-security-basic-authentication
I have created a couple of rest endpoints like this :
#RestController
public class PostController {
#Autowired
PostCommentService postCommentService;
#Autowired
PostService postService;
#GetMapping("/comment")
public PostComment getComment(#RequestParam Long id) {
return postCommentService.findPostCommentById(id);
}
#PostMapping("/createPost")
public void createPost(#RequestBody PostDTO body){
postService.createPost(body);
}
}
Now for security I am using spring like this:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
This is the config class for spring security:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private MyBasicAuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/comment").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
http.addFilterAfter(new CustomFilter(),
BasicAuthenticationFilter.class);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder().encode("password"))
.authorities("ROLE_USER");
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
The CustomFilter looks like this:
public class CustomFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
}
And this is the AuthenticationEntryPoint:
#Component
public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
throws IOException {
response.addHeader("WWW-Authenticate", "Basic realm= + getRealmName() + ");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("HTTP Status 401 - " + authEx.getMessage());
}
#Override
public void afterPropertiesSet(){
setRealmName("spring");
super.afterPropertiesSet();
}
}
Now the problem is that whenever I try to send a POST request I end up getting this error message:
HTTP Status 401 - Full authentication is required to access this resource
I have tried two approaches to send the request, one via postman
And the second one via curl:
curl -i --user admin:password --request POST --data {"text":"this is a new Post"} http://localhost:8080/createPost
I am at my wits' end here, hence the need to create this post. Any help will be much appreciated.
This is the curl response in case it might shed light on the matter:
1.1 401
Set-Cookie: JSESSIONID=6FE84B06E90BE7F2348C0935FE3DA971; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
WWW-Authenticate: Basic realm= + getRealmName() +
Content-Length: 75
Date: Thu, 10 Sep 2020 13:47:14 GMT
HTTP Status 401 - Full authentication is required to access this resource
This happens because Spring Security comes with CSRF protection enabled by default (and for a good reason). You can read about Cross Site Request Forgery here. In your case the CsrfFilter detects missing or invalid CSRF token and you're getting the 401 response. The easiest way to make your example work would be to disable csrf-ing in your security configuration but, of course, you shouldn't do this in a real application.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers( "/comment").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
http.addFilterAfter(new CustomFilter(),
BasicAuthenticationFilter.class);
}

How to setup CORS on user login

I'm getting Not injecting HSTS header error but still have no idea after googling this message.
o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#30cc5ff
What I have done is below.
API request http://localhost:8083/api/v1/users/login
Web config
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL)
.permitAll();
http.csrf().disable().addFilterBefore(corsFilter, AuthorizationFilter.class)
.authorizeRequests()
.antMatchers("/api/v1/**").authenticated();
protected AuthenticationFilter getAuthenticationFilter() throws Exception {
final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager());
filter.setFilterProcessesUrl("/api/v1/users/login");
return filter;
}
CorsFilter
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
// without this header jquery.ajax calls returns 401 even after successful login and SSESSIONID being succesfully stored.
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Origin, Content-Type, Version");
response.setHeader("Access-Control-Expose-Headers", "X-Requested-With, Authorization, Origin, Content-Type");
final HttpServletRequest request = (HttpServletRequest) servletRequest;
if (!request.getMethod().equals("OPTIONS")) {
filterChain.doFilter(request, response);
} else {
// do not continue with filter chain for options requests
}
}
#Override
public void destroy() {
}
}
HSTS stands for Http Strict Transport Security and is one of the default headers being included when using Spring Security.
If you have your own security configuration set up and are sure you can disable the HSTS security header, use:
http.headers().httpStrictTransportSecurity().disable();

Full authentication exception in spring boot

Hello I have following Security config file.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class)
.authorizeRequests()
.antMatchers("/myservices/**/**").permitAll()
.antMatchers("/knowndata").permitAll()
.antMatchers("/guidata/**").permitAll()
.antMatchers("/textdata/**").access("hasRole('ROLE_ADMIN')")
.anyRequest().authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.httpBasic();
http.csrf().disable();
}
and the following CORSFilter
#Component
public class CORSFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-auth-token,authorization, content-type, xsrf-token");
response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(request, response);
}
}
}
Still I get Full authentication required exception when accessing the myservices.

Spring Boot CORS configuration is not accepting authorization header

Angular2 app is sending a HTTP GET request with X-AUTH-TOKEN header value to the Spring Boot. Every time request.getHeader("X-AUTH-TOKEN") returns null.
Interestingly it works fine if I send the request from ARC client or any other rest client.
I have also spent a great amount of time making sure that Angular HTTP GET request is sending JWT token.
Angular code
getCandidatesByUserId(userId: number): Observable<Candidate[]> {
let headers = new Headers({ 'X-AUTH-TOKEN': 'let-jwt-test-token-in' });
console.log('Token is '+ headers.get('X-AUTH-TOKEN'));
return this.http.get(this.url+userId+'/candidates', {
headers: headers
})
.map((response: Response) => <Candidate[]> response.json())
.do(data => console.log('All: '+ JSON.stringify(data)))
.catch(this.handleError);
}
JWTFilter
#Override
public void doFilter(ServletRequest request, ServletResponse res, FilterChain filterChain)
throws IOException, ServletException {
try {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-AUTH-TOKEN, Content-Type, Accept");
response.setHeader("Access-Control-Expose-Headers", "X-AUTH-TOKEN, Content-Type");
HttpServletRequest httpRequest = (HttpServletRequest) request;
Map<String, String> blackListedTokenMap =
(Map<String, String>) ((HttpServletRequest) request)
.getSession()
.getServletContext()
.getAttribute(WebAppListener.TOKEN_BLACK_LIST_MAP);
String authToken = authenticationService.getToken(httpRequest);
if (authToken != null && blackListedTokenMap.containsValue(authToken)) {
throw new RuntimeException("token invalidated");
}
UserAuthentication authentication = (UserAuthentication) authenticationService.getAuthentication(httpRequest);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
SecurityContextHolder.getContext().setAuthentication(null);
} catch (RuntimeException e) {
((HttpServletResponse) res).sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
SpringSecurityConfig
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(new HttpSessionCsrfTokenRepository())
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("*/*"));
http
.exceptionHandling()
.and()
.anonymous()
.and()
.servletApi()
.and()
.headers()
.cacheControl();
http
//.addFilterBefore(corsFilter, ChannelProcessingFilter.class)
.authorizeRequests()
.antMatchers("/resources/**").permitAll()// allow for static resources
.antMatchers("/signup").permitAll()
.antMatchers("/forgot").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/reset").permitAll()
.antMatchers("/health").permitAll()
.antMatchers("/hello").permitAll()
.antMatchers("/").permitAll()
.antMatchers("/reset_pw").permitAll()
.anyRequest().authenticated()
.and()
.addFilterAfter(new JJWTFilter(tokenAuthenticationService),
UsernamePasswordAuthenticationFilter.class);
}
Console Logs
I resolved with :
//Define class with this annotation
#Configuration
public class CorsConfig {
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
// return new CorsFilter(source);
final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
#Bean
public WebMvcConfigurer mvcConfigurer() {
return new WebMvcConfigurerAdapter() {
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "PUT", "POST", "GET", "OPTIONS");
}
};
}
}
You can define this class and add in your boot spring class #ComponentScan(basePackageClasses= CorsConfig.class)
Or just use the above method inside the boot class.
Then should work.

Resources