I am trying to write a web-app that allows authentication by either JDBC or Google/Facebook; using Spring Security 5.0.x. I have valid Google Client Id and Secret. The OAuth2 web-flow is taking me correctly to Google for account selection and consent, but the callback to the redirect_uri is failing with a 404. I can't see what I'm doing wrong.
@Configuration
@EnableScheduling
@EnableWebSecurity
public class WebSecurityConfig
extends WebSecurityConfigurerAdapter
{
private static final Logger _logger = LogManager.getLogger (WebSecurityConfig.class);
private static String
SuccessUrl = "/api/auth/login-success",
FailureUrl = "/api/auth/login-failure",
LogoutUrl = "/api/auth/logout-done";
private static String
PGoogleId = "oauth2.google.id",
PGoogleSecret = "oauth2.google.secret",
PFacebookId = "oauth2.facebook.id",
PFacebookSecret = "oauth2.google.secret";
private final List<ClientRegistration> _regns;
@Autowired
private AuthSuccessHandler _success;
@Autowired
private AuthFailureHandler _failure;
@Autowired
private DataSource _source;
@Autowired
private MezoUserManager _userManager;
/**
* Sole Constructor
*/
public WebSecurityConfig ()
{
_regns = new ArrayList<> ();
}
@Autowired
public void setPropertiesFactory (
PropertiesFactoryBean factory)
throws IOException, AddressException
{
Properties p = factory.getObject ();
extractIdSecret (CommonOAuth2Provider.GOOGLE.getBuilder ("google"), PGoogleId, PGoogleSecret, p);
extractIdSecret (CommonOAuth2Provider.FACEBOOK.getBuilder ("facebook"), PFacebookId, PFacebookSecret, p);
}
private void extractIdSecret (
ClientRegistration.Builder builder,
String idKey,
String secretKey,
Properties properties)
{
String id = properties.getProperty (idKey);
String secret = properties.getProperty (secretKey);
if (StringUtils.isBlank (id) || StringUtils.isBlank (secret))
return;
_regns.add (builder.clientId (id).clientSecret (secret).build ());
}
@Override
protected void configure (
HttpSecurity http)
throws Exception
{
_success.setUrl (SuccessUrl);
_failure.setUrl (FailureUrl);
JdbcTokenRepositoryImpl repo = new JdbcTokenRepositoryImpl ();
repo.setDataSource (_source);
http
.authorizeRequests ()
.antMatchers ("/api/profile/**").authenticated ()
.antMatchers ("/api/users/**").hasAuthority (Authority.ROLE_ADMIN.name ())
.antMatchers ("/api/**").permitAll ()
.and ()
.exceptionHandling ()
.authenticationEntryPoint (new Http403ForbiddenEntryPoint())
.and ()
.formLogin ()
.loginProcessingUrl ("/login")
.loginPage ("/")
.successHandler (_success)
.failureHandler (_failure)
.and ()
.logout ()
.logoutUrl ("/logout")
.logoutSuccessUrl (LogoutUrl)
.and ()
.rememberMe ()
.tokenRepository (repo)
.tokenValiditySeconds (1209600)
.rememberMeParameter ("remember-me")
.and ()
.csrf ().disable ();
if (!_regns.isEmpty ())
{
http.oauth2Login ()
.clientRegistrationRepository (new InMemoryClientRegistrationRepository (_regns));
_logger.debug ("OAuth2 entabled");
}
}
@Override
protected void configure (
AuthenticationManagerBuilder builder)
throws Exception
{
DaoAuthenticationProvider provider = new DaoAuthenticationProvider ();
provider.setUserDetailsService (_userManager);
provider.setPasswordEncoder (encoder ());
builder.authenticationProvider (provider);
builder.userDetailsService (_userManager);
}
@Bean
public BCryptPasswordEncoder encoder ()
{
return new BCryptPasswordEncoder ();
}
}
The callback from Google is going to the right place:
http://localhost:8080/mezo/login/oauth2/code/google?state=.....
But my webapp complains with:
HTTP Status 404 - /mezo/login
Can anyone see what I've missed in my config? Why hasn't Spring Security automatically setting up the filters for the callback uri?
Note that the login using JDBC currently works with this config.
The fix was to be a bit more permissive with the antMatchers(). In particular, extending:
.antMatchers ("/api/**").permitAll ()
with:
.antMatchers ("/api/**", "/login/**").permitAll ()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With