User is not stored in the database Spring - spring

I write application on Spring with security. I made database with users and I can Login in app as user from database. But when I try to register new user in DB it don't stored.
I have no errors, just redirect to main page.
If I uncomment autologin string I get Null Point EX.
Here is structure of my app:
UserServiceImpl.class:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.Set;
import com.ya.pokupay.dao.RoleDAO;
import com.ya.pokupay.dao.UserDAO;
import com.ya.pokupay.model.Role;
import com.ya.pokupay.model.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserDAO userDao;
#Autowired
private RoleDAO roleDao;
#Override
public void save(User user) {
System.out.println("HERE");
Set<Role> roles = new HashSet<>();
roles.add(roleDao.getOne(1L));
user.setRoles(roles);
System.out.println("user: " + user);
userDao.save(user);
}
#Override
public User findByUsername(String username) {
return userDao.findByUsername(username);
}
}
controller method:
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute("userForm") User userForm, BindingResult bindingResult, Model model) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.save(userForm);
//securityService.autoLogin(userForm.getUsername(), userForm.getConfirmPassword());
return "redirect:/all";
}
UserDetailServiceImpl:
import com.ya.pokupay.dao.UserDAO;
import com.ya.pokupay.model.Role;
import com.ya.pokupay.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashSet;
import java.util.Set;
public class UserDetailsServiceImpl implements UserDetailsService{
#Autowired
private UserDAO userDao;
#Override
#Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDao.findByUsername(username);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
}
}
If it can help I can add some more code or settings.
EDITED:
UserDAO:
import com.ya.pokupay.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserDAO extends JpaRepository<User, Long> {
User findByUsername(String username);
}

I didn't find solution, so I just wrote my own implementation of asve method and it works for me.

Related

Registration Issue with Spring Security 401 with Postman

I had problem in spring security when I try to register a new user and tested it in the postman it keep giving me a 401 unauthorized response.
I checked all the filters, control, service repository and everything I already checked all the issues here and even searched a lot about it in google but no answer I hope some one had the answer.
this is the code below:
this is the Security Configuration:
package app.gym.v1.Utility.Config;
import app.gym.v1.Utility.Filter.JwtAccessDeniedHandler;
import app.gym.v1.Utility.Filter.JwtAuthenticationEntryPoint;
import app.gym.v1.Utility.Filter.JwtAuthorizationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import static app.gym.v1.Utility.Constant.SecurityConstant.*;
import static org.springframework.security.config.http.SessionCreationPolicy.*;
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private JwtAuthorizationFilter jwtAuthorizationFilter;
private JwtAccessDeniedHandler jwtAccessDeniedHandler;
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
public SecurityConfig(
JwtAuthorizationFilter jwtAuthorizationFilter,
JwtAccessDeniedHandler jwtAccessDeniedHandler,
JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint,
#Qualifier("userDetailsService")UserDetailsService userDetailsService,
BCryptPasswordEncoder bCryptPasswordEncoder) {
this.jwtAuthorizationFilter = jwtAuthorizationFilter;
this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint;
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().cors().and()
.sessionManagement().sessionCreationPolicy(STATELESS)
.and().authorizeRequests().antMatchers(PUBLIC_URLS).permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(jwtAccessDeniedHandler)
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);
}
#Bean
#Override
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManagerBean();
}
}
this is the Resource code:
package app.gym.v1.Resource;
import app.gym.v1.Model.User;
import app.gym.v1.Service.UserService;
import app.gym.v1.Utility.Exception.Domain.*;
import app.gym.v1.Utility.Exception.ExceptionHandling;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import static org.springframework.http.HttpStatus.OK;
#RestController
#RequestMapping(path = {"/","/user"})
public class UserControl extends ExceptionHandling {
private UserService userService;
#Autowired
public UserControl(UserService userService) {
this.userService = userService;
}
#PostMapping("/register")
public ResponseEntity<User> register(#RequestBody User user) throws UserNotFoundException, UsernameExistException, EmailExistException, IOException {
User newUser = userService.register(user.getUsername(), user.getEmail(), user.getPassword(), user.getRole());
return new ResponseEntity<>(newUser, OK);
}
}
this is the user implementation service:
package app.gym.v1.Utility.Impl;
import app.gym.v1.Model.User;
import app.gym.v1.Model.UserPrincipal;
import app.gym.v1.Repo.UserRepo;
import app.gym.v1.Service.UserService;
import app.gym.v1.Utility.Exception.Domain.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import javax.transaction.Transactional;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import static app.gym.v1.Utility.Constant.UserImplConstant.*;
import static app.gym.v1.Utility.Enums.Role.*;
import static org.apache.commons.lang3.StringUtils.*;
#Service
#Transactional
#Qualifier("UserDetailsService")
public class UserServiceImpl implements UserService, UserDetailsService {
private Logger LOGGER = LoggerFactory.getLogger(getClass());
private UserRepo userRepo;
private BCryptPasswordEncoder passwordEncoder;
#Autowired
public UserServiceImpl(UserRepo userRepo, BCryptPasswordEncoder passwordEncoder) {
this.userRepo = userRepo;
this.passwordEncoder = passwordEncoder;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepo.findUserByUsername(username);
if (user == null) {
LOGGER.error("User with this phone number does not exist: " + username);
throw new UsernameNotFoundException("User with this phone number does not exist: " + username);
}else {
user.setLastLoginDateDisplay(user.getLastLoginDate());
user.setLastLoginDate(new Date());
userRepo.save(user);
UserPrincipal userPrincipal = new UserPrincipal(user);
LOGGER.info("Retrieving user with this phone number" + username);
return userPrincipal;
}
}
#Override
public User register(String username, String email, String password, String role) throws UserNotFoundException, UsernameExistException, EmailExistException {
validateNewUsernameAndEmail(EMPTY, username, email);
User user = new User();
user.setUserId(generateUserId());
user.setUsername(username);
user.setEmail(email);
user.setPassword(encodePassword(password));
user.setRole(USER.name());
user.setAuthorities(USER.getAuthorities());
user.setJoinDate(new Date());
user.setActive(true);
user.setNotLocked(true);
userRepo.save(user);
return user;
}
private String encodePassword(String password) {
return passwordEncoder.encode(password);
}
private String generateUserId() {
return RandomStringUtils.randomNumeric(20);
}
private String generatePassword() {
return RandomStringUtils.randomAlphanumeric(20);
}
private User validateNewUsernameAndEmail(String currentUsername, String newUsername, String newEmail) throws UserNotFoundException, UsernameExistException, EmailExistException {
User userByNewUsername = findUserByUsername(newUsername);
User userByNewEmail = findUserByEmail(newEmail);
if(isNotBlank(currentUsername)) {
User currentUser = findUserByUsername(currentUsername);
if(currentUser == null) {
throw new UserNotFoundException(NO_USER_FOUND_BY_USERNAME + currentUsername);
}
if(userByNewUsername != null && !currentUser.getId().equals(userByNewUsername.getId())) {
throw new UsernameExistException(USERNAME_ALREADY_EXISTS);
}
if(userByNewEmail != null && !currentUser.getId().equals(userByNewEmail.getId())) {
throw new EmailExistException(EMAIL_ALREADY_EXISTS);
}
return currentUser;
} else {
if(userByNewUsername != null) {
throw new UsernameExistException(USERNAME_ALREADY_EXISTS);
}
if(userByNewEmail != null) {
throw new EmailExistException(EMAIL_ALREADY_EXISTS);
}
return null;
}
}
}
the problem is with the registration my route is that(localhost:8080/user/register) or (localhost:8080/register).
I put a constant for them to make a public urls.
You need to annotate your SecurityConfig class with #Configuration or it won't be picked up.
If you do not have a custom security configuration set up properly, the application will use the default Spring Boot autoconfiguration which restricts access to all endpoints.

Creating role requirement for accessig a webpage with Spring BOOT

I am trying to add to website I created a requirement for user to be logged-in in order to access content and also split 3 types of users: non logged-in person, admin and standard user. I struggle a lot with it as I was unable to find a guide that would both explain it to me and work properly at the same time. Could you guys please help me and tell em what am I doing wrong? I spent 6 days trying to get this logging in feature to work and I feel compleatly lost at this point because I tried so many different codes and approaches from guides I found. As for my database I am using SQL Workbench.
The problem is (at least I think this is the problem) that in SecurityConfig in configure method I am not actually passing Role of the User (hasAnyRole('Admin')). I was trying to do it in many ways but I don't really udnerstand how am I supposed to pass Role to it.
Here is my controller package:
MainController:
package Projekt.ProjektAI.controller;
import Projekt.ProjektAI.entities.Book;
import Projekt.ProjektAI.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import java.security.Provider;
import java.util.List;
#Controller
public class MainController {
private BookService service;
#Autowired
public MainController(BookService service){
this.service = service;
}
#RequestMapping("/")
public String viewNormalHomePage(Model model) {
List<Book> listBooks = service.listAll();
model.addAttribute("listBooks", listBooks);
return "indexNormal";
}
#RequestMapping("/admin")
public String viewAdminHomePage(Model model) {
List<Book> listBooks = service.listAll();
model.addAttribute("listBooks", listBooks);
return "index";
}
#RequestMapping("/user")
public String viewUserHomePage(Model model) {
List<Book> listBooks = service.listAll();
model.addAttribute("listBooks", listBooks);
return "indexStandard";
}
#RequestMapping("/admin/new")
public String showNewBookPage(Model model) {
Book book = new Book();
model.addAttribute("book", book);
return "newBook";
}
#RequestMapping("/admin/edit/{id}")
public ModelAndView showEditBookPage(#PathVariable(name = "id") Long id) {
ModelAndView mav = new ModelAndView("editBook");
Book book = service.get(id);
mav.addObject("book", book);
return mav;
}
#RequestMapping(value = "/admin/save", method = RequestMethod.POST)
public String saveBook(#ModelAttribute("book") Book book) {
service.save(book);
return "redirect:/";
}
#RequestMapping("/admin/delete/{id}")
public String deleteBook(#PathVariable(name = "id") Long id) {
service.delete(id);
return "redirect:/";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model) {
return "login";
}
#RequestMapping(value = "/user", method = RequestMethod.GET)
public String userIndex() {
return "user/index";
}
}
UserRegistrationController:
package Projekt.ProjektAI.controller;
import javax.validation.Valid;
import Projekt.ProjektAI.service.UserService;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.entities.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/registration")
public class UserRegistrationController {
#Autowired
private UserService userService;
#ModelAttribute("user")
public UserRegistrationDTO userRegistrationDto() {
return new UserRegistrationDTO();
}
#GetMapping
public String showRegistrationForm(Model model) {
return "registration";
}
#PostMapping
public String registerUserAccount(#ModelAttribute("user") #Valid UserRegistrationDTO userDto,
BindingResult result) {
User existing = userService.findByEmail(userDto.getEmail());
if (existing != null) {
result.rejectValue("email", null, "There is already an account registered with that email");
}
if (result.hasErrors()) {
return "registration";
}
userService.save(userDto);
return "redirect:/registration?success";
}
}
Entities package:
Book entity:
package Projekt.ProjektAI.entities;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
#Entity
#Getter
#Setter
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String autor;
#Column
private String tytul;
#Column
private String gatunek;
#Column
private float cena;
public Book() {
}
#Override
public String toString() {
return "Book{" +
"id=" + id +
", autor='" + autor + '\'' +
", tytul='" + tytul + '\'' +
", gatunek='" + gatunek + '\'' +
", cena=" + cena +
'}';
}
}
Role entity:
package Projekt.ProjektAI.entities;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
#Getter
#Setter
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
protected Role() {}
public Role(String name) {
this.name = name;
}
#Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
User entity:
package Projekt.ProjektAI.entities;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.Collection;
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Table(uniqueConstraints = #UniqueConstraint(columnNames = "email"))
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;
private String password;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(
name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(
name = "role_id", referencedColumnName = "id"))
private Collection <Projekt.ProjektAI.entities.Role> roles;
public Collection <Projekt.ProjektAI.entities.Role> getRoles() {
return roles;
}
public void setRoles(Collection <Projekt.ProjektAI.entities.Role> roles) {
this.roles = roles;
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", password='" + "*********" + '\'' +
", roles=" + roles +
'}';
}
}
registration DTO package:
FieldMatch interface:
package Projekt.ProjektAI.registrationDTO;
import javax.validation.Payload;
import javax.validation.Constraint;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
#Target({
TYPE,
ANNOTATION_TYPE
})
#Retention(RUNTIME)
#Constraint(validatedBy = FieldMatchValidator.class)
#Documented
public #interface FieldMatch {
String message() default "{constraints.field-match}";
Class < ? > [] groups() default {};
Class < ? extends Payload > [] payload() default {};
String first();
String second();
#Target({
TYPE,
ANNOTATION_TYPE
})
#Retention(RUNTIME)
#Documented
#interface List {
FieldMatch[] value();
}
}
Field Match Validator:
package Projekt.ProjektAI.registrationDTO;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.beanutils.BeanUtils;
public class FieldMatchValidator implements ConstraintValidator <Projekt.ProjektAI.registrationDTO.FieldMatch, Object > {
private String firstFieldName;
private String secondFieldName;
#Override
public void initialize(final Projekt.ProjektAI.registrationDTO.FieldMatch constraintAnnotation) {
firstFieldName = constraintAnnotation.first();
secondFieldName = constraintAnnotation.second();
}
#Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
try {
final Object firstObj = BeanUtils.getProperty(value, firstFieldName);
final Object secondObj = BeanUtils.getProperty(value, secondFieldName);
return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
} catch (final Exception ignore) {}
return true;
}
}
User Registration DTO:
package Projekt.ProjektAI.registrationDTO;
import lombok.Getter;
import lombok.Setter;
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
#Projekt.ProjektAI.registrationDTO.FieldMatch.List({
#Projekt.ProjektAI.registrationDTO.FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match"),
#Projekt.ProjektAI.registrationDTO.FieldMatch(first = "email", second = "confirmEmail", message = "The email fields must match")
})
#Getter
#Setter
public class UserRegistrationDTO {
#NotEmpty
private String firstName;
#NotEmpty
private String lastName;
#NotEmpty
private String password;
#NotEmpty
private String confirmPassword;
#Email
#NotEmpty
private String email;
#Email
#NotEmpty
private String confirmEmail;
#AssertTrue
private Boolean terms;
}
repositories package:
Book Repository
package Projekt.ProjektAI.repositories;
import Projekt.ProjektAI.entities.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface BookRepository extends JpaRepository<Book, Long> {
}
User Repository:
package Projekt.ProjektAI.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import Projekt.ProjektAI.entities.User;
#Repository
public interface UserRepository extends JpaRepository < User, Long > {
User findByEmail(String email);
}
security package:
package Projekt.ProjektAI.security;
import Projekt.ProjektAI.entities.User;
import Projekt.ProjektAI.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import Projekt.ProjektAI.service.UserService;
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserService userService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/new", "/edit/{id}", "/save", "/delete/{id}")
.access("hasAnyRole('Admin')")
.and()
.authorizeRequests()
.antMatchers("/registration**","/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.permitAll();
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
}
service package:
Book Service:
package Projekt.ProjektAI.service;
import Projekt.ProjektAI.entities.Book;
import Projekt.ProjektAI.repositories.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class BookService {
private BookRepository repo;
#Autowired
public BookService(BookRepository repo)
{
this.repo =repo;
}
public List<Book> listAll() {
return repo.findAll();
}
public void save(Book book) {
repo.save(book);
}
public Book get(long id) {
return repo.findById(id).get();
}
public void delete(long id) {
repo.deleteById(id);
}
}
User Service interface:
package Projekt.ProjektAI.service;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.entities.User;
import org.springframework.security.core.userdetails.UserDetailsService;
public interface UserService extends UserDetailsService {
User findByEmail(String email);
User save(UserRegistrationDTO registration);
}
User Service Implementation:
package Projekt.ProjektAI.service;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import Projekt.ProjektAI.service.UserService;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.entities.User;
import Projekt.ProjektAI.entities.Role;
import Projekt.ProjektAI.service.UserService;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.repositories.UserRepository;
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private BCryptPasswordEncoder passwordEncoder;
public User findByEmail(String email) {
return userRepository.findByEmail(email);
}
public User save(UserRegistrationDTO registration) {
User user = new User();
user.setFirstName(registration.getFirstName());
user.setLastName(registration.getLastName());
user.setEmail(registration.getEmail());
user.setPassword(passwordEncoder.encode(registration.getPassword()));
user.setRoles(Arrays.asList(new Role("ROLE_USER")));
return userRepository.save(user);
}
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("Invalid username or password.");
}
return new org.springframework.security.core.userdetails.User(user.getEmail(),
user.getPassword(),
mapRolesToAuthorities(user.getRoles()));
}
private Collection < ? extends GrantedAuthority > mapRolesToAuthorities(Collection < Role > roles) {
return roles.stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
}
application properties:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.url=jdbc:mysql://localhost:3366/projektai?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=admin
Thank you very much for any tips!

Missing grant type error

I am just trying to learn OAuth. I wrote some code to test it out. when I am submitting a request I am getting
{
"error": "invalid_request",
"error_description": "Missing grant type"
}
error in postman.
import java.util.Optional;
//import static org.assertj.core.api.Assertions.tuple;
import java.util.stream.Stream;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.springframework.security.core.userdetails.User;
//import org.omg.PortableInterceptor.ACTIVE;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.stereotype.Service;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#SpringBootApplication
public class SpringAuthServiceApplication {
#Bean
CommandLineRunner clr(AccountRepository accountRepository){
return args -> {
Stream.of("name1, password1", "name2, password2", "name3, password3", "name4, password4")
.map(tpl -> tpl.split(",") )
.forEach(tpl -> accountRepository.save(new Account(tpl[0], tpl[1], true)));
};
}
public static void main(String[] args) {
SpringApplication.run(SpringAuthServiceApplication.class, args);
}
}
#Configuration
#EnableAuthorizationServer
class AuthServiceConfiguration extends AuthorizationServerConfigurerAdapter{
private final AuthenticationManager authenticationManager;
public AuthServiceConfiguration(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("html5")
.secret("password")
.authorizedGrantTypes("password")
.scopes("openid");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(this.authenticationManager);
}
}
#Service
class AccountUserDetailService implements UserDetailsService{
private final AccountRepository accountRepository;
public AccountUserDetailService(AccountRepository accountRepository) {
// super();
this.accountRepository = accountRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
return accountRepository.findByUsername (username)
.map(account -> new User(account.getUsername(),
account.getPassword(), account.isActive(), account.isActive(), account.isActive(), account.isActive(),
AuthorityUtils.createAuthorityList("ROLE_ADMIN", "ROLE_USER") )
)
.orElseThrow(() -> new UsernameNotFoundException("Couldn't fine user name " + username + "!") ) ;
}
/*#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return accountRepository.findByUsername(username)
.map(account -> {
boolean active = account.isActive();
return new User(
account.getUsername(),
account.getPassword(),
active, active, active, active,
AuthorityUtils.createAuthorityList("ROLE_ADMIN", "ROLE_USER"));
})
.orElseThrow(() -> new UsernameNotFoundException(String.format("username %s not found!", username)));
}*/
}
interface AccountRepository extends JpaRepository<Account, Long>{
Optional<Account> findByUsername(String username);
}
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
class Account{
public Account(String username, String password, boolean active) {
//super();
this.username = username;
this.password = password;
this.active = active;
}
#GeneratedValue #Id
private long id;
private String username, password;
private boolean active;
}
Here is what I am sending in postman:
In the header tab:
Content-Type: application/json
Authorization: Basic aHRtbDU6cGFzc3dvcmQ=
In the Authorization tab:
type is Basic Auth
Username: html5
Password: password
Body tab, selected form data and sending the following:
username: username
password: password1
grant_type: password
scope: openid
client_id: html5
client_secret: password
OAuth2 is looking for parameters in the form of a query string inside the request body, aka application/x-www-form-urlencoded.
Change your Content-Type to application/x-www-form-urlencoded and check x-www-form-urlencoded instead of form-data.

Authentication failed (Bad Credentuals) in Spring Security with hibernate for REST

I've created a spring boot app with spring-data-rest.
My Rest API is working just fine. Then I imported the spring security. I've also done configurations after referring to a number of Web resources.
However, each time I send a request, I get Bad Credential Error The below are my codes
User.java
package com.innaun.model;
import org.springframework.data.rest.core.annotation.RestResource;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Set;
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#Column(unique = true, nullable = false)
private String username;
#NotNull
#RestResource(exported = false )
private String password;
#NotNull
private boolean enabled;
#OneToMany
private Set<UserRole> userRoles = new HashSet<UserRole>(0);
public User() {
}
public User(String username, String password, boolean enabled) {
this.username = username;
this.password = password;
this.enabled = enabled;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
UserRole.java
package com.innaun.model;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
#Entity
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userRoleId;
#NotNull
private String userRole;
#ManyToOne
private User user;
public UserRole() {
}
public UserRole(String userRole, User user) {
this.userRole = userRole;
this.user = user;
}
public Long getUserRoleId() {
return userRoleId;
}
public void setUserRoleId(Long userRoleId) {
this.userRoleId = userRoleId;
}
public String getUserRole() {
return userRole;
}
public void setUserRole(String userRole) {
this.userRole = userRole;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserRepository.java
package com.innaun.model;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource
public interface UserRepository extends CrudRepository<User, Long>{
User findByUsername(#Param("user") String user);
}
UserRoleRepository.java
package com.innaun.model;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource
public interface UserRoleRepository extends CrudRepository<UserRole, Long> {
}
AppUserDetailsService.java
package com.innaun.model;
import com.innaun.model.UserRepository;
import com.innaun.model.UserRole;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Service("appUserDetailsService")
public class AppUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Transactional
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
com.innaun.model.User user = userRepository.findByUsername(s);
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRoles());
return buildUserForAuthentication(user, authorities);
}
private User buildUserForAuthentication(com.innaun.model.User user, List<GrantedAuthority> authorities){
return new User(user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles){
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
for (UserRole userRole : userRoles){
setAuths.add(new SimpleGrantedAuthority(userRole.getUserRole()));
}
List<GrantedAuthority> result = new ArrayList<GrantedAuthority>(setAuths);
return result;
}
}
ApplicationRESTSecurity.java
package com.innaun;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableWebSecurity
public class ApplicationRESTSecurity extends WebSecurityConfigurerAdapter {
#Qualifier("appUserDetailsService")
#Autowired
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and().httpBasic()
.and().csrf()
.disable();
}
}
Also, I've added the below to add a test user to the database
package com.innaun;
import com.innaun.model.User;
import com.innaun.model.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
public class PitchuApplication {
public static void main(String[] args) {
SpringApplication.run(PitchuApplication.class, args);
}
#Bean
CommandLineRunner init(UserRepository userRepository) {
return (args) -> {
userRepository.save(new User("myuser", "mypassword", true));
};
}
}
Just as I thought, the database now has the above user and the user is enabled.
Screenshot of the User data table
All the other tables are blank.
However when I tried the curl
curl -u myuser:mypassword localhost:8080
it returned
{"timestamp":1489090315435,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"}
Can anyone explain where did I went wrong.
Your configuration looks fine to me. So, my best guess is that your password column in your database has length less than 60 which is the length of the hash BCrypt will produce.
I figured it out. And this was so simple mistake. the password I used to save a new user in the userRepository is raw instead of encrypted. I figured it out by:
//Create a new password encoder
private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//Encode the password
String password = "mypassword";
String hashedPassword = passwordEncoder.encode(password);
//Create the user with the encoded password
User user = new User(myuser, hashedPassword, true);
//then persist
userRepository.save(user);

Spring Security : UserDetailsService works only once

I seem to be missing something fundamental here:
#SpringBootApplication
public class Application {
User u = new User("USER", "PASSWORD",AuthorityUtils.createAuthorityList(
"ROLE_USER", "ROLE_ADMINISTRATOR"));
#Bean
public UserDetailsService userDetailsService() {
// returning a new User object works fine for every request
return username -> new User("USER", "PASSWORD",
AuthorityUtils.createAuthorityList(
"ROLE_USER", "ROLE_ADMINISTRATOR"));
// returning a previously created User object
// works only for the first request,
// subsequent requests get a 401 error
// return username -> u;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
This Spring Boot (v1.5.1) application using the spring-boot-starter-security dependency knows of only one user as of now. Also, all of its endpoints should only be accessible to this very user. In all of the working examples I have seen, the UserDetailsService always returns a new object of type User, just like in the above example.
But when it returns a previously created object (like the object named u above), only the first request gets authenticated. Why ?
A good complete example, with JPA as well, can be found here
This is just an example. Password still needs to be encrypted/secured.
Application.java
package demo;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.repository.CrudRepository;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableGlobalMethodSecurity(securedEnabled = true)
public class Application extends WebMvcConfigurerAdapter {
#Controller
protected static class HomeController {
#RequestMapping("/")
#Secured("ROLE_ADMIN")
public String home(Map<String, Object> model) {
model.put("message", "Hello World");
model.put("title", "Hello Home");
model.put("date", new Date());
return "home";
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/access").setViewName("access");
}
#Bean
public ApplicationSecurity applicationSecurity() {
return new ApplicationSecurity();
}
#Order(Ordered.HIGHEST_PRECEDENCE)
#Configuration
protected static class AuthenticationSecurity extends
GlobalAuthenticationConfigurerAdapter {
#Autowired
private Users users;
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(users);
}
}
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.authorizeRequests().antMatchers("/login").permitAll().anyRequest()
.fullyAuthenticated().and().formLogin().loginPage("/login")
.failureUrl("/login?error").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).and()
.exceptionHandling().accessDeniedPage("/access?error");
// #formatter:on
}
}
}
#Service
class Users implements UserDetailsService {
private UserRepository repo;
#Autowired
public Users(UserRepository repo) {
this.repo = repo;
}
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = repo.findByName(username);
if (user == null) {
return null;
}
List<GrantedAuthority> auth = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE_USER");
if (username.equals("admin")) {
auth = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE_ADMIN");
}
String password = user.getPassword();
return new org.springframework.security.core.userdetails.User(username, password,
auth);
}
}
#Repository
interface UserRepository extends CrudRepository<User, Long> {
User findByName(String name);
}
#Entity
class User {
#GeneratedValue
#Id
private Long id;
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
I believe it is due to the Spring User object purging the password after authentication
from -> https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/userdetails/User.html
Note that this implementation is not immutable. It implements the CredentialsContainer interface, in order to allow the password to be erased after authentication. This may cause side-effects if you are storing instances in-memory and reusing them. If so, make sure you return a copy from your UserDetailsService each time it is invoked.

Resources