Hello i have been trying to configure spring to have it return JWT token if user/pass is authenticated to LDAP Server; Consider the use case below ;
On the above diagram, i have configured WebSecurity to check/filter out requests with Bearer. See code below
WebSecurityConfig.java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
JwtAuthorizationTokenFilter authenticationTokenFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
// Configure Web Security
// Allow only /auth/
// Disallow all others
http
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST,
"/auth/**")
.permitAll()
.anyRequest().authenticated();
//Custom JWT
http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// disable page caching
http.headers().cacheControl();
}
}
AuthCtrl.java
@RestController
@RequestMapping("auth")
public class AuthCtrl {
private static final Logger logger = LoggerFactory.getLogger(AuthCtrl.class);
@Autowired
@Qualifier("authenticationManagerImpl")
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
@Qualifier("userDetailsServiceImpl")
private UserDetailsService userDetailsService;
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody String post(@RequestBody Map<String, String> credentials) {
logger.info("POST: {} | {} ",credentials.get("username"), credentials.get("password"));
String username = credentials.get("username");
String password = credentials.get("password");
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
// Reload password post-security so we can generate the token
final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
final String token = jwtTokenUtil.generateToken(userDetails);
return token;
} catch (DisabledException e) {
throw new AuthenticationException("User is disabled!", e);
} catch (BadCredentialsException e) {
throw new AuthenticationException("Bad credentials!", e);
}
}
@ExceptionHandler({AuthenticationException.class})
public ResponseEntity<String> handleAuthenticationException(AuthenticationException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage());
}
}
Above configuration was based on a youtube guide i've seen and also a pull from a demo source in git. Great help!, credits to the owners. Got to understand how filters work somehow.
The above source can already filter out all protected API and sends out unauthorized back as a response when it is not authorized. The only api i allowed to be accessed anonymously is the authentication api /auth
. It can already receive the request and passed through the web filters.
But i can't quite figure out how to authenticate the said request to LDAP server and sends out a JWT token. On the guide i've read they are getting the user information on a database.
I've read some documentation on LDAP configuration in WebConfiguration, but i can't relate it to my current filters.
Please check the below link I have created it using spring 4.
Instead of .ldif file on classpath configure your own ldap server.
https://github.com/merugu/springsecurity/tree/master/ldapauthenticationjwttoken
The only differences is for Spring 5 you should use advance password encoding algorithm like Bcryptpasswordencoder.As the LDAPpasswordEncoder is deprecated.
Happy coding!