Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring 5 LDAP Authentication and JWT Token as response

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 ;

enter image description here

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.

like image 947
lemoncodes Avatar asked Sep 02 '18 06:09

lemoncodes


1 Answers

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!

like image 77
Amit Avatar answered Sep 21 '22 12:09

Amit