'String name = authentication.getName(); Authentication is null when debugging?

I am trying to allow an authenticated user to upload an image to an AWS S3 Bucket. I am able to push to the S3 bucket okay, but when I try to save to the logged in user's profile DB, it does not save since I am unable to pull the logged in user's username as it is null when I tried debugging. I am using JWT to authenticate and Spring Security but am not sure what I am doing wrong. I even tried logging in through my React.js fronted (Successfully) but it still does not pull the user's username for some reason. Any help would be appreciated.

enter image description here

Upload Method:

@PostMapping("/image_upload")
    public ResponseEntity<?> singleFileUpload(@RequestParam("file") MultipartFile file,
                                              RedirectAttributes redirectAttributes,
                                              Model model, Authentication authentication,
                                              UserProfile userProfile) {

        //Check if POST is empty
        if (file.isEmpty()) {

            return ResponseEntity.ok(new MessageResponse( "Please select a file to upload"));
        }

        //Hard coded bucketName -> linked to AWS
        String bucketName = "bucket";

        //Add timestamp to name to prevent duplicate names
        String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();

        //getting aws access
        AWSCredentials credentials = new BasicAWSCredentials(accessKey, accessSecret);

        //Building S3Client connection
        AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                .withRegion(Regions.Region)
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(region).build();

        try {
            //PUSH TO BUCKET
            File fileObj = convertMultiPartFileToFile(file);
            s3Client.putObject(new PutObjectRequest(bucketName, fileName, fileObj));
            fileObj.delete();

            //Show Successful Upload
            ResponseEntity.ok(new MessageResponse(fileName +": YOOOOOO")); //Does not print either, even though upload goes to S3.
           // redirectAttributes.addFlashAttribute("message", fileName + ": SuccessFully Uploaded On AWS S3");

            //Logged in user's username
            String name = authentication.getName(); //null
           CustomUserDetails customUser = (CustomUserDetails) userDetailsService.loadUserByUsername(name);
            Long userId = customUser.getId();
            //Find UserProfile by id
           userProfile = userProfRepo.findByuserId(userId);

            //Set resource name to

            userProfile.setProfile_img(fileName);

            //Save database changes
            userProfRepo.save(userProfile);

        } catch (Exception e) {
            e.printStackTrace();
        }
        model.addAttribute("userProfile", userProfile);
        return ResponseEntity.ok(new MessageResponse("File Upload Successful"));

    }

WebSecurityConfig.java:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.App.security.jwt.AuthEntryPointJwt ;
import com.App.security.jwt.AuthTokenFilter;
import com.App.security.services.CustomUserDetailsService;
/**
 * Web security configuration
 */
@Configuration
@EnableWebSecurity()
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    CustomUserDetailsService userDetailsService;
    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;
    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }
    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers("/api/auth/**").permitAll()
                .antMatchers("/api/v1/**").permitAll()
                .antMatchers("/api/test/**").permitAll()
                .anyRequest().authenticated().and().formLogin().loginPage("/login").defaultSuccessUrl("/profile").permitAll().and()
                .logout()
                .logoutSuccessUrl("/login")
                .permitAll();
        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

login Method:

    @PostMapping("/login")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtUtils.generateJwtToken(authentication);

        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        List<String> roles = userDetails.getAuthorities().stream()
                .map(item -> item.getAuthority())
                .collect(Collectors.toList());
        return ResponseEntity.ok(new JwtResponse(jwt,
                userDetails.getId(),
                userDetails.getUsername(),
                userDetails.getEmail(),
                roles));
    }


Solution 1:[1]

Couple of things you can look

  1. is the user passing the correct JWT token.
  2. Get Authentication from SecurityContextHolder.getContext().getAuthentication()
  3. make sure your authenticationJwtTokenFilter is setting the authentication object correctly.
  4. You have set the sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) so all the requests that need to be authenticated needs to contain jwt token.

Also, your code is a mess.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ekansh Rastogi