I’m really new to Jhipster. I played with Symfony before and did a course on spring boot, so rest application are still kind of new to me.
I was tasked to add authentification to an app previously copied from an another jhipster app.
I already had several bug due to this copy, so i know it was a bad idea to begin with.
The application is just displaying data, the data object is a “site”.
Here some of the endpoints a use :
/login
/sites
/api/sites
When authenticated, the “sites” endpoint display a html page and make a request to my backend for a list of sites. The sites display correctly.
When not authenticated, the “sites” endpoint wrongly display a html page and make a request to my backend for a list of sites. The request is answered by a error 500 because the endpoint /api/sites is unattainable, which is what i want.
I don’t want the “sites” page to be displayed, i want this page to redirect me to the login page for authentification.
Here is my SecurityConfiguration.java :
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final JHipsterProperties jHipsterProperties;
private final RememberMeServices rememberMeServices;
private final CorsFilter corsFilter;
private final SecurityProblemSupport problemSupport;
public SecurityConfiguration(
RememberMeServices rememberMeServices,
CorsFilter corsFilter,
JHipsterProperties jHipsterProperties,
SecurityProblemSupport problemSupport
) {
this.rememberMeServices = rememberMeServices;
this.corsFilter = corsFilter;
this.problemSupport = problemSupport;
this.jHipsterProperties = jHipsterProperties;
}
@Bean
public AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() {
return new AjaxAuthenticationSuccessHandler();
}
@Bean
public AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler() {
return new AjaxAuthenticationFailureHandler();
}
@Bean
public AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler() {
return new AjaxLogoutSuccessHandler();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/app/**/*.{js,html}")
.antMatchers("/i18n/**")
.antMatchers("/content/**")
.antMatchers("/swagger-ui/**")
.antMatchers("/test/**")
.antMatchers("/management/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.addFilterBefore(corsFilter, CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.rememberMe()
.rememberMeServices(rememberMeServices)
.rememberMeParameter("remember-me")
.key(jHipsterProperties.getSecurity().getRememberMe().getKey())
.and()
.authenticationProvider(getProvider())
.formLogin()
.loginProcessingUrl("/api/authentication")
.successHandler(ajaxAuthenticationSuccessHandler())
.failureHandler(getCustomAjaxAuthenticationFailureHandler())
.permitAll()
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(ajaxLogoutSuccessHandler())
.permitAll()
.and()
.headers()
.contentSecurityPolicy(jHipsterProperties.getSecurity().getContentSecurityPolicy())
.and()
.referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
.and()
.featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; fullscreen 'self'; payment 'none'")
.and()
.frameOptions()
.deny()
.and()
.authorizeRequests()
.antMatchers("/api/authenticate").permitAll()
.antMatchers("/api/register").permitAll()
.antMatchers("/api/activate").permitAll()
.antMatchers("/api/account/reset-password/init").permitAll()
.antMatchers("/api/account/reset-password/finish").permitAll()
.antMatchers("/api/admin/**").hasAuthority(AuthoritiesConstants.ADMIN)
//Doens't do anything ? .antMatchers("/app/sites").hasAuthority(AuthoritiesConstants.USER)
//Doens't do anything ? .antMatchers("/sites").hasAuthority(AuthoritiesConstants.USER)
.antMatchers("/api/**").authenticated()
.antMatchers("/management/**").permitAll();
}
@Bean
public AuthenticationProvider getProvider() {
return new AdesiLdapAuthentication();
}
@Bean
public CustomAjaxAuthenticationFailureHandler getCustomAjaxAuthenticationFailureHandler() {
return new CustomAjaxAuthenticationFailureHandler();
}
}
The first thing i tried was adding the authority to the different restController, but i can’t find the one for the pages :
Here is the api/sites RestController :
Here is the api/sites RestController :
@GetMapping("/sites")
@PreAuthorize("hasAuthority("" + AuthoritiesConstants.USER + "")")
public ResponseEntity<List<SiteDTO>> getAllSites(SiteCriteria criteria, Pageable pageable){
log.debug("REST request to get Traitements by criteria: {}");
// gestion de la pagination
pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(),
Sort.by(Sort.Direction.DESC, SORTING_BY_ID));
List<SiteDTO> page = siteQueryService.findSitesByCriteria(criteria, pageable);
return ResponseEntity.ok().body(page);
}
I tried adding Authority rules on the sites endpoint, doesn’t seem to do any changes.
I also have access an another application (named B for clarity), based on the same stack, which is perfectly functionnal.
Of coursed i tried to compare the sources, the SecurityConfiguration files have no differences.
Can’t find any rules on security for the correctly secured endpoint in the B Application.
Ultimately i would like to know how the B application did this security, but i’m kind of desperate and any way to secure will suffice.
Thanks in advance !
Albert Guihard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.