Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a RESTful login API using Spring Security?

I just started to work with Spring security and just implemented HTTP basic authentication that works fine.

Now I would like to create login endpoint and try to get authenticated user.

I am not sure what do I have to use for that? I did read online lots of stuff but not sure where to start.

Any tip would be very appreciated!

This is the code that used for authentication.

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userDetailsService)
            .passwordEncoder(encodePWD());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
            .csrf().disable();
        http
            .httpBasic()
                .and()
            .authorizeRequests()
                .antMatchers("/rest/**").permitAll()
                .and()
            .authorizeRequests()
                .antMatchers("/secure/**").hasAnyRole("ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .permitAll();
    }

    @Bean
    public BCryptPasswordEncoder encodePWD() {
        return new BCryptPasswordEncoder();
    }
}

CustomUserDetailsService.java

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        CustomUserDetails userDetails = null;

        if(user != null){
            userDetails = new CustomUserDetails();
            userDetails.setUser(user);
        }else{
            throw new UserNotFoundException("User doesn't exist with this username: " + username);
        }
        return userDetails;
    }
}

CustomUserDetails.java

@Getter
@Setter
public class CustomUserDetails implements UserDetails {

    private User user;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole())).collect(Collectors.toSet());

    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

UPDATE

I am sending my data like JSON using Postman

{
    "username": "admin",
    "password": "admin35"      
}
like image 915
user9347049 Avatar asked Nov 22 '25 06:11

user9347049


1 Answers

In a traditional MVC Spring Boot application, Spring Security would check the SecurityContextHolder for the authentication information. If not found, then you would be redirected to a login page.

For a REST API endpoint, you would not have a typical login form sent from the server. You would collect the credentials from a form on the client (AngularJS, ReactJS, VueJs, iOS app, etc) and POST the credentials to an endpoint to retrieve user information. For example, the following authenticates the user, then returns the authenticated user information to the client.

private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    
    @GetMapping("/user")
    public ResponseEntity<UserResponse> getUser(@AuthenticationPrincipal DmsUserDetails dmsUser) {
        
        logger.info("User " + dmsUser.getFirstName() + " " + dmsUser.getLastName() + " logged in.");
        
        UserResponse user = new UserResponse();
        user.setUserId(dmsUser.getUserId());
        user.setFirstName(dmsUser.getFirstName());
        user.setLastName(dmsUser.getLastName());
        user.setEmail(dmsUser.getUsername());
        
        return ResponseEntity.ok(user);
    }

The client would keep track of whether the user is logged in, and pass either a cookie or a token on each subsequent request.

In this case, I've named the endpoint /user, but you can call it /login if you prefer.

like image 95
Tony Langworthy Avatar answered Nov 23 '25 19:11

Tony Langworthy