This is my first project in Spring. I am trying to get the username of the logged in user but it returns null
. I have also tried the AuthenticationPrincipal
annotation and other ways as well, still it returns null
.
WebSecurityConfiguration
class:
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{
@Autowired
private UserDetailsService customUserDetailsService;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean ();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(encoder());
}
@Override
protected void configure (HttpSecurity http) throws Exception {
http
.csrf().disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/login**").permitAll()
.anyRequest().authenticated();
}
public PasswordEncoder encoder() {
return NoOpPasswordEncoder.getInstance();
}
}
AuthorizationServerConfiguration
class:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.userDetailsService(userDetailsService)
.approvalStoreDisabled();
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
}
ResourceServerConfiguration
class:
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{
@Autowired
TokenStore tokenStore;
@Autowired
DataSource dataSource;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("scout").tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/oauth/token", "/oauth/authorize **").permitAll();
http
.requestMatchers()
.antMatchers("/api/patients/**")
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/patients/{\\d+}").access("hasAnyRole('PATIENT', 'DOCTOR')")
.antMatchers("/api/patients/{\\d+}/medical-records").access("hasAnyRole ('PATIENT', 'DOCTOR')")
.antMatchers("/api/patients/medical-records/{\\\\d+}/prescriptions").access("hasAnyRole('PATIENT', 'DOCTOR')")
.antMatchers("/api/patients/**").access("hasRole('PATIENT')")
.and()
.requestMatchers()
.antMatchers("/api/doctors/**")
.and()
.authorizeRequests()
.antMatchers("/api/doctors/**").access("hasRole('DOCTOR')");
}
}
Below is the controller:
@GetMapping("/doctors")
public Doctor getDoctor(Authentication user) {
System.out.println(user.getName());
return doctorService.getDoctor(user.getName());
}
************************************Update********************************
I am using oauth2 for security. I am trying to get the username of the logged in user in my controller above. I have tried to print the Principal object and I get
org.springframework.security.oauth2.provider.OAuth2Authentication@24d14be1: Principal: com.prescribr.rest.service.CustomUserDetails@56d40b2f; Credentials: [PROTECTED]; Authenticated: true; Details: remoteAddress=0:0:0:0:0:0:0:1, sessionId=<SESSION>, tokenType=bearertokenValue=<TOKEN>; Granted Authorities: ROLE_DOCTOR
On the other note, principal.getName() returns null.
I am using the access token in my header while sending the request as below in postman.
authorization: bearer theToken
CustomUserDetails class:
public class CustomUserDetails extends Users implements UserDetails {
private static final long serialVersionUID = -8170449272852748515L;
public CustomUserDetails(final Users user) {
super(user);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return super.getPassword();
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return super.getEmail();
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
}
CustomUserDetailsService class:
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UsersRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<Users> usersOptional = userRepository.findByEmail(email);
Users user = null;
if(usersOptional.isPresent()) {
System.out.println(usersOptional.isPresent());
user = usersOptional.get();
}else {
throw new RuntimeException("Email is not registered!");
}
return new CustomUserDetails(user);
}
}
Users class:
@Entity
@Table(name="users")
public class Users {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="email")
private String email;
@Column(name="password")
private String password;
@Column(name="active")
private int active;
@OneToMany(cascade=CascadeType.ALL,
fetch=FetchType.EAGER
)
@JoinColumn(name="user_id")
private Set<Role> roles;
public Users() {}
public Users(Users user) {
this.id = user.id;
this.firstName = user.firstName;
this.lastName = user.lastName;
this.email = user.email;
this.password = user.password;
this.active = user.active;
this.roles = user.roles;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Thanks again!