Getting sign in Browser pop-up instead of navigate to own jsp - spring

Spring-boot login demo.
Getting Sign in browser pop up for following code.
Instead of pop-up I want to navigate to my own
#ComponentScan
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("user");
}
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers("/resources/**");
}
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/user", "/index.html", "/").permitAll().anyRequest()
.authenticated();
}
}

Related

Authentication in Spring Web Security issue

I am going to set up background Spring Authentication by a custom class that implemented UserDetailsService. As said in the documentation method loadUserByUsername calls each time when user try to login, but it don't in the case below.
#Component
public class AuthenticationUserDetailsService implements UserDetailsService {
#Autowired
private PersonRepository personRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Person> personByUserName = personRepository.findPersonByUserName(username);
Person person = personByUserName.
orElseThrow(() -> new UsernameNotFoundException("User with username has not found"));
return new User(username, person.getPassword(), Collections.emptyList());
}
}
I try to use several alternatives to set up configure(HttpSecurity http) method in WebSecurityConfig class.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("api/person/login")
.usernameParameter("username")
.passwordParameter("password");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/index.html", "/", "/home", "/api/person/login").permitAll()
.anyRequest().authenticated();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.
authorizeRequests().
anyRequest().authenticated()
.and().
formLogin().
loginProcessingUrl("/login").
usernameParameter("username").
passwordParameter("password");
}
Registration DaoAuthenticationProvider:
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(getAuthenticationProvider());
}
#Bean
public DaoAuthenticationProvider getAuthenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(authenticationUserDetailsService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return daoAuthenticationProvider;
}
Could anyone explain, where is error, and why loadUserByUsername method doesn't call at all?
The Angular 8 UI part uses to login.
public loginPerson(person: Person): Observable<Person> {
let url = "http://localhost:8080/login";
return this.httpClient.post<Person>(url, {userName: person.username, password: person.password});
}

Spring permitAll() and ignorning() doesn't work

I'm trying to configure Spring-Boot 2 application with in-memory authorization and it drive me crazy...
I need to secure all resources except /news.
I have created this configuration beans following the Spring's docs but Spring Security isn't permit GET method on /news:
#Slf4j
#Configuration
#EnableWebSecurity
public class ApplicationAuthentication extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.GET,"/news");
}
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER")
.and()
.withUser("admin")
.password("admin")
.roles("USER", "ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET,"/news")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
I'm using spring-boot 2.0.4.RELEASE,
Can someone help me?

How to disable the 'Authentification required popup' in Spring server configuration?

The route /gateways needs authentication.
When /gateways is accessed in the browser I am redirected to /login and the following form appears:
If /gateways is accessed from an angular2 app the following popup appears:
My spring security configuration is the following:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static String REALM="Authentication";
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("cris").password("123").roles("ADMIN");
auth.inMemoryAuthentication().withUser("felix").password("felix123").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.formLogin()
.and()
.authorizeRequests()
.antMatchers("/user", "/vehicles", "/signin", "/isautheticated").permitAll().anyRequest()
.authenticated();
}
// Access-Control-Allow-Origin header to be present
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
/* To allow Pre-flight [OPTIONS] request from browser */
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
So how can the popup be disabled?
You should specify formLogin() instead of httpBasic() in your configuration. your configure method should look like this.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login");
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.formLogin()
.and()
.authorizeRequests()
.antMatchers("/user", "/vehicles", "/signin", "/isautheticated").permitAll().anyRequest()
.authenticated();
}
I think your request from angular2 is taking an invalid Authorization Basic header, it was handled by BasicAuthenticationFilter, and it threw a AuthenticationException, and start to entry point.
You can implement your own entry point that implements AuthenticationEntryPoint, and then inject to BasicFilter, the default entry point is BasicAuthenticationEntryPoint. As you can see, it will return a WWW-Authenticate response header.
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\"");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
authException.getMessage());
}

Oath2 + spring + jwt

What I want to achieve:
An Oauth2 server in spring with java configuration
Login page on the Oauth2 server
A user that accesses the client will be redirected to the login page on the Oauth2 server
After login he is automatically redirected to /oauth/authorize for the authentication code (JWT-token)
Afterwards he is redirected back to the client
The client will get the access token from oauth/token (JWT-token)
Right now, I have the login page, and the use can be verified (DB check).
Oauth is configured, but every path redirects to this login page (even if he already logged in)
My WebSecurityConfig:
#Autowired
MyUserDetailsService userService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
//.antMatcher("/**")
.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("oauth/authorize").access("hasRole('ROLE_ADMIN')")
.antMatchers("oauth/token").access("hasRole('ROLE_ADMIN')")
.and()
.csrf()
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
// This works for basic authentication:
/* http.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.antMatchers("/db/**").access("hasRole('ROLE_ADMIN') and hasRole('DBA')")
.and().formLogin().loginPage("/login")
.usernameParameter("username").passwordParameter("password")
.and().csrf()
.and().exceptionHandling().accessDeniedPage("/Access_Denied");*/
}
My AuthorizationServerConfiguration:
#Autowired
private AuthenticationConfiguration authenticationConfiguration;
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
return new JwtAccessTokenConverter();
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("isAnonymous() || hasRole('ROLE_ADMIN')")
.checkTokenAccess("hasRole('ROLE_ADMIN')");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationConfiguration.getAuthenticationManager())
.accessTokenConverter(accessTokenConverter());
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("some-client")
.secret("some-client")
.authorizedGrantTypes("authorization_code", "password", "implicit") //enabled all for testing
.scopes("read", "trust")
.redirectUris("http://anywhere?key=value");
}
#Autowired
public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
this.authenticationConfiguration = authenticationConfiguration;
}
When I try to access /oauth/authorize, i get redirected to the login page, but after login, I just get redirected to the login page again. Altough the correct user was verified in the database... Any help?

JHipster OAuth2 server - login page for /oauth/authorize

tl;dr;
I want to make custom working login page when user is redirected to /oauth/authorize, in jhipster template app I manage to display my login page but it is just redirecting to itself no matter what credentials are used or if I remove
.requestMatchers().antMatchers("/oauth/authorize")
from WebSecurityConfigurerAdapter page works fine but /oauth/token returns:
error: "unauthorized"
error_description: "There is no client authentication. Try adding an appropriate authentication filter."
Long description:
I'm using jhipster template app for resource server with some small admin front end. Except of this I want other client apps to be able to use my resource server, but user login should stay on my app.
Example Journey:
Client app is redirecting user to my app:
127.0.0.1:8080/oauth/authorize?
response_type=code&client_id=kbExplorer&redirect_uri=http://localhost
Login page is served for a user
User choose scopes he wants to give
Server is redirecting to redirect_uri with authorization code
App uses code to get refresh token
127.0.0.1:8080/oauth/token?grand_type=authorization_code&code={code}
This is typical journey.
Problem starts when I want to change basic http login window, to my own login page.
First thing I've done was changing:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Inject
private UserDetailsService userDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/scripts/**/*.{js,html}")
.antMatchers("/bower_components/**")
.antMatchers("/i18n/**")
.antMatchers("/assets/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/api/register")
.antMatchers("/api/activate")
.antMatchers("/api/account/reset_password/init")
.antMatchers("/api/account/reset_password/finish")
.antMatchers("/test/**")
.antMatchers("/console/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
//.httpBasic().realmName("LES")
//.and()
.requestMatchers().antMatchers("/oauth/authorize")
.and()
.authorizeRequests()
.antMatchers("/api/logput").permitAll()
.antMatchers("/oauth/authorize").authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.formLogin().loginPage("/login").permitAll().and().csrf().disable();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
return new SecurityEvaluationContextExtension();
}
}
Thanks to that I'm getting custom login page served from mvc controller:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
But there is a problem right now, when I go to /oauth/authorize login page is served and it is ok, except of whatever you will put there it will always redirect you back to this login page.
I've noticed that if I only remove:
#Override
public void configure(HttpSecurity http) throws Exception {
http
//.httpBasic().realmName("LES")
//.and()
// This is the line I'm removing:
//.requestMatchers().antMatchers("/oauth/authorize")
//.and()
.authorizeRequests()
.antMatchers("/api/logput").permitAll()
.antMatchers("/oauth/authorize").authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.formLogin().loginPage("/login").permitAll().and().csrf().disable();
}
Whole login works fine. But now admin app stops (this is pure jhipster angularjs template). Just opening this app produces an error:
error: "Internal Server Error"
exception: "java.lang.IllegalStateException"
message: "Request processing failed; nested exception is java.lang.IllegalStateException: User not found!"
path: "/api/account"
status: 500
timestamp: "2016-01-22T11:33:08.286+0000"
Attempt to log in by default grand_type=password produce:
error: "unauthorized"
error_description: "There is no client authentication. Try adding an appropriate authentication filter."
This is my OAuth2ServerConfiguration (Basically its pure jhipser template):
#Configuration
public class OAuth2ServerConfiguration {
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
#Inject
private AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler;
#Override
public void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(ajaxLogoutSuccessHandler)
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")) // csfr (my own change)
.disable()
.headers()
.frameOptions().disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/api/authenticate").permitAll()
.antMatchers("/api/register").permitAll()
.antMatchers("/api/logs/**").hasAnyAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/api/**").authenticated()
.antMatchers("/metrics/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/health/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/dump/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/shutdown/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/beans/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/configprops/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/liquibase/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/protected/**").authenticated();
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Inject
Environment env;
#Inject
private DataSource dataSource;
#Inject
private JHipsterProperties jHipsterProperties;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Inject
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
if(env.acceptsProfiles(Constants.SPRING_PROFILE_PRODUCTION)) {
clients.jdbc(dataSource);
}else{
clients
.jdbc(dataSource)
.withClient(jHipsterProperties.getSecurity().getAuthentication().getOauth().getClientid())
.scopes("read", "write")
.authorities(AuthoritiesConstants.ADMIN, AuthoritiesConstants.USER)
.authorizedGrantTypes("password", "refresh_token", "authorization_code", "implicit")
.secret(jHipsterProperties.getSecurity().getAuthentication().getOauth().getSecret())
.accessTokenValiditySeconds(jHipsterProperties.getSecurity().getAuthentication().getOauth().getTokenValidityInSeconds())
.and()
.withClient("kbExplorer")
.scopes("read", "write")
.authorities(AuthoritiesConstants.ADMIN, AuthoritiesConstants.USER)
.authorizedGrantTypes("password", "refresh_token", "authorization_code", "implicit")
.secret("kbExplorerAppSecret")
.accessTokenValiditySeconds(5)
.refreshTokenValiditySeconds(1800);
}
}
}
}
Question is:
How to make login page works, without breaking api in same time?
I had wrong matchers, login page was not working in my first option because I had no matcher for "/login" in configure method.
SecurityConfiguration class should be like this:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/oauth/authorize","/login", "/oauth/confirm_access")
.and()
.authorizeRequests()
.antMatchers("/oauth/authorize").authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.csrf().disable();
}

Resources