I have a custom UserDetailsService:
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private AccountRepository accountRepository;
#Autowired
private PasswordEncoder passwordEncoder;
private static Logger logger = LoggerFactory.getLogger(JWTLoginFilter.class);
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
CustomUserDetails account = accountRepository.findByUsername(username);
if (account != null) {
return account;
} else {
throw new UsernameNotFoundException("could not find the user '" + username + "'");
}
}
public void saveUser(String userName, String password) {
CustomUserDetails userDetails = new CustomUserDetails(userName, passwordEncoder.encode(password), true, true, true,true, AuthorityUtils.commaSeparatedStringToAuthorityList("USER_ROLE"));
accountRepository.save(userDetails);
logger.debug("New user with username " + userName + " was created");
}
}
and I have a sign up filter (which handles creating new users) and extends AbstractAuthenticationProcessingFilter:
public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter {
#Autowired
private CustomUserDetailsService userDetailService;
private static Logger logger = LoggerFactory.getLogger(JWTLoginFilter.class);
public JWTSignupFilter(String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url, HttpMethod.POST.toString()));
setAuthenticationManager(authManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
CustomUserDetails creds = new ObjectMapper().readValue(request.getInputStream(), CustomUserDetails.class);
if (userDetailService.loadUserByUsername(creds.getUsername()) != null) {
logger.debug("Duplicate username " + creds.getUsername());
throw new AuthenticationException("Duplicate username") {
private static final long serialVersionUID = 1L;
};
}
userDetailService.saveUser(creds.getUsername(), creds.getPassword());
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(),creds.getPassword()));
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
TokenAuthenticationService.addAuthentication(response, auth.getName());
chain.doFilter(request, response);
}
}
I get null pointer exception when the execution reaches userDetailService.loadUserByUsername, which means autowiring didn't work.
I tried implementing ApplicationContextAware like the following, but it is still Null. I also annotated JWTSignupFilter with #Service but it didn't work either. Any idea how to fix this issue ?
public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
private CustomUserDetailsService userDetailService;
.....
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
userDetailService = applicationContext.getBean(CustomUserDetailsService.class);
}
}
This is the overriden configure method in WebSecurityConfigurerAdapter, where login filter comes in to the play:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout().logoutUrl("/logout").logoutSuccessHandler(logoutHandler).logoutSuccessUrl("/login").invalidateHttpSession(true)
.and()
// We filter the api/signup requests
.addFilterBefore(
new JWTSignupFilter("/signup", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// We filter the api/login requests
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(
new JWTAuthenticationFilter(userDetailsServiceBean()),
UsernamePasswordAuthenticationFilter.class);
}
Try this:
Add below code into your configuration file:
#Bean
public JWTSignupFilter jWTSignupFilter() throws Exception {
return new JWTSignupFilter("/login", authenticationManager());
}
Add below line into your WebSecurityConfigurerAdapter extended class
#Autowired
JWTLoginFilter jWTSignupFilter
and replace
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
with
.addFilterBefore(
jWTSignupFilter,
UsernamePasswordAuthenticationFilter.class)
Updated
Your WebSecurityConfigurerAdapter extended class should look like so:
public Class CustomConfigurationClass extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout().logoutUrl("/logout").logoutSuccessHandler(logoutHandler).logoutSuccessUrl("/login").invalidateHttpSession(true)
.and()
// We filter the api/signup requests
.addFilterBefore(
jWTSignupFilter(),
UsernamePasswordAuthenticationFilter.class)
// We filter the api/login requests
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(
new JWTAuthenticationFilter(userDetailsServiceBean()),
UsernamePasswordAuthenticationFilter.class);
}
#Bean
public JWTSignupFilter jWTSignupFilter() throws Exception {
return new JWTSignupFilter("/signup", authenticationManager());
}
}
Related
Hello everyone I am writing Authentication using Spring Security and JWT tokens.
I add my own filter in the configuration. But the request is not included in the filter. Therefore, all requests to any address are executed, even without a token.
SecurityConfig.class
#Configuration
#EnableWebSecurity
#ComponentScan("my.pac")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtFilter jwtFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/register", "/auth").permitAll()
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Filter
#Component
public class JwtFilter extends GenericFilterBean {
public static final String AUTHORIZATION = "Authorization";
#Autowired
private JwtProvider jwtProvider;
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
logger.info("do filter...");
String token = getTokenFromRequest((HttpServletRequest) servletRequest);
if (token != null && jwtProvider.validateToken(token)) {
String userLogin = jwtProvider.getLoginFromToken(token);
CustomUserDetails customUserDetails = customUserDetailsService.loadUserByUsername(userLogin);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(customUserDetails, null, customUserDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(servletRequest, servletResponse);
}
private String getTokenFromRequest(HttpServletRequest request) {
String bearer = request.getHeader(AUTHORIZATION);
if (hasText(bearer) && bearer.startsWith("Bearer ")) {
return bearer.substring(7);
}
return null;
}}
upd:
this option also does not work for the filter:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/register", "/auth").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
You only specified .antMatchers("/register", "/auth").permitAll(), to force authentication to other things you must add .anyRequest().authenticated()
So something like this
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/register", "/auth").permitAll()
.and()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
I'm a junior web developper and I need to customize the 403 error page using react js, I've found other projects implementing the AccessDeniedHandler interface but I don't know how to use it in my Security Configuration class.
This is my CustomAccessDeniedHandler class :
#Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private static Logger logger = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
#Override
public void handle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AccessDeniedException e) throws IOException, ServletException {
System.out.println("accessDenied");
Authentication auth
= SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
logger.info("User '" + auth.getName()
+ "' attempted to access the protected URL: "
+ httpServletRequest.getRequestURI());
}
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/accessDenied");
}
}
This is the Security Configuration class :
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
AppUserService userDetailsService;
#Autowired
private AccessDeniedHandler accessDeniedHandler;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {})
.and()
.authenticationProvider(getProvider())
.formLogin()
.loginPage("/login")
.successHandler(new AuthentificationLoginSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
.invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/api/categories").hasAuthority("USER")
.antMatchers("/api/createCategory").hasAuthority("ADMIN")
.anyRequest().permitAll();
}
private class AuthentificationLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_OK);
}
}
private class AuthentificationLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
#Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_OK);
}
}
#Bean
public AuthenticationProvider getProvider() {
AppAuthProvider provider = new AppAuthProvider();
provider.setUserDetailsService(userDetailsService);
return provider;
}
#Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
}
What you have to do is to create #Bean
#Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
which you already have and then add that handler in http security object like this:
http.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {}) //remove this line or use Http401UnauthorizedEntryPoint instead
.and()
.authenticationProvider(getProvider())
.formLogin()
.loginPage("/login")
.successHandler(new AuthentificationLoginSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
.invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/api/categories").hasAuthority("USER")
.antMatchers("/api/createCategory").hasAuthority("ADMIN")
.anyRequest().permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
As you can see you are missing:
.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler());
Additional, remove
#Autowired
private AccessDeniedHandler accessDeniedHandler;
because you shouldn't autowire bean, you should create it with custom implementation.
EDIT:
If you have #RestControllerAdvice or #ControllerAdvice as global exception handler you should do following:
#ExceptionHandler(Exception.class)
public ResponseEntity<?> exception(Exception exception) throws Exception {
if (exception instanceof AccessDeniedException) {
throw exception;
}
...
then it should work because when you throw exception it will go to custom handler which we do what you wrote. Also you can debug ExceptionTranslationFilter method handleSpringSecurityException
code from ExceptionTranslationFilter
private void handleSpringSecurityException(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, RuntimeException exception)
throws IOException, ServletException {
if (exception instanceof AuthenticationException) {
logger.debug(
"Authentication exception occurred; redirecting to authentication entry point",
exception);
sendStartAuthentication(request, response, chain,
(AuthenticationException) exception);
}
else if (exception instanceof AccessDeniedException) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
logger.debug(
"Access is denied (user is " + (authenticationTrustResolver.isAnonymous(authentication) ? "anonymous" : "not fully authenticated") + "); redirecting to authentication entry point",
exception);
sendStartAuthentication(
request,
response,
chain,
new InsufficientAuthenticationException(
messages.getMessage(
"ExceptionTranslationFilter.insufficientAuthentication",
"Full authentication is required to access this resource")));
}
else {
logger.debug(
"Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
exception);
accessDeniedHandler.handle(request, response,
(AccessDeniedException) exception);
}
}
}
where you can see that
accessDeniedHandler.handle(request, response,(AccessDeniedException) exception);, in you caseCustomAccessDeniedHandler, get called.
I just tried it and it is working fine with (I have #ControllerAdvice as global exception handler)
EDIT2:
You have to remove this line
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {})
from SecurityConfig, or change it to use Http401UnauthorizedEntryPoint instead. This is the problem in your case.
I am using spring spring security 5.1.4 and i am trying to authenticate user with custom authentication.
SecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
CustomUserDetailsService customUserDetailsService;
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
#Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
/* #Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
*/
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
private CustomAuthenticationProvider authProvider;
#Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/api/auth/**")
.permitAll()
.antMatchers("/app/**").permitAll()
.antMatchers("/api/user/checkUsernameAvailability", "/api/user/checkEmailAvailability")
.permitAll()
.antMatchers(HttpMethod.GET, "/api/polls/**", "/api/users/**")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
and my custom authenticationprovider is
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Autowired
private UserRepository userRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
Optional<Tbluser> dbUser = userRepository.findByUsername(authentication.getName());
Tbluser dUser = dbUser.get();
String dbPassword = dUser.getPassword();
boolean passwordsMatch = passwordEncoder.matches(password,dbPassword);
if(!passwordsMatch) {
throw new BadCredentialsException("Invalid username/password");
}
return new UsernamePasswordAuthenticationToken(username, password, Collections.emptyList());
}
#Override
public boolean supports(Class<?>aClass) {
return aClass.equals(UsernamePasswordAuthenticationToken.class);
}
}
so whenever i debug the password i provide in seen in the plain text i.e in authentication object but the password i fetch from database is encoded form.
boolean passwordsMatch = passwordEncoder.matches(password,dbPassword);
is always false.
how do i authenticate them ?
I have created a JWT authentication filter for my Spring Rest backend. Creating a JWT doesn't appear to be an issue, however with my current setup, any request is authenticated, no request triggers a 401 despite the fact that the client is not passing any tokens in the header.
My WebSecurityConfig:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true,
jsr250Enabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private JwtAuthenticationEntryPoint unauthorizedHandler;
private CustomUserDetailsService customUserDetailsService;
#Autowired
public WebSecurityConfig(final JwtAuthenticationEntryPoint unauthorizedHandler,
final CustomUserDetailsService customUserDetailsService) {
this.unauthorizedHandler = unauthorizedHandler;
this.customUserDetailsService = customUserDetailsService;
}
#Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
#Bean
public JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler() {
return new JwtAuthenticationSuccessHandler();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* {#inheritDoc}
*/
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.cors()
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.antMatcher("/api")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
/**
* Sets security evaluation context.
*
* #return {#link SecurityEvaluationContextExtension}
*/
#Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
return new SecurityEvaluationContextExtension();
}
}
I have set this up such that all requests require authorisation. My JwtAuthenticationEntryPoint is as expected: a generic 401 error being thrown.
My JwtAuthenticationFilter:
#Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Autowired
private JwtTokenProvider tokenProvider;
#Autowired
private CustomUserDetailsService customUserDetailsService;
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain
filterChain) throws ServletException, IOException {
logger.debug("Filtering request for JWT header verification");
try {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
String username = tokenProvider.getUserIdFromJWT(jwt);
UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken
(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
logger.debug("Attempting to get token from request header");
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
Found the problem.
I had to include a reference to the filter in my web.xml file, this isn't picked up automatically using component scanner.
something like:
<filter>
<filter-name>jwtFilter</filter-name>
<filter-class>com.path.to.JwtFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jwtFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I configure oauth2(resource server and auth server) in my spring boot app, but how to perform authentication now? How to use grants which I described in authentication server?
And how to perform autologin when new user has been registered?
#Configuration
public class OAuth2ServerConfig {
#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("/logout")
.logoutSuccessHandler(ajaxLogoutSuccessHandler)
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/authorize"))
.disable()
.headers()
.frameOptions().disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/admin").hasAnyAuthority("ADMIN");
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static final String CLIENTID = "app";
private static final String PROP_SECRET = "secret";
private static final Integer TOKEN_VALIDITY_SECONDS = -1;
#Inject
private OAuth2AccessTokenRepository oAuth2AccessTokenRepository;
#Inject
private OAuth2RefreshTokenRepository oAuth2RefreshTokenRepository;
#Bean
public TokenStore tokenStore() {
return new MongoDBTokenStore(oAuth2AccessTokenRepository, oAuth2RefreshTokenRepository);
}
#Inject
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(CLIENTID)
.scopes("read", "write")
.authorities("USER", "ADMIN")
.authorizedGrantTypes("password", "refresh_token")
.secret(PROP_SECRET)
.accessTokenValiditySeconds(TOKEN_VALIDITY_SECONDS);
}
}
}
You should have something like this:
#Component
public class CustomAuthenticationProvider
implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
if (shouldAuthenticateAgainstThirdPartySystem()) {
// use the credentials
// and authenticate against the third-party system
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
} else {
return null;
}
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
UsernamePasswordAuthenticationToken.class);
}
}
and register it to your SecurityConfig
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider authProvider;
#Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
}