Reputation: 95
Initially the principal object in the authentication of spring security is a string, that simply contains the user id. By defining a custom user detail service or a custom authentication provider and extending the user object in spring security, the user information should be stored in the principal object. But no matter which of both i choose, the principal object always stays a string. For security we are using an authentication server with oauth2.
This is the version with a customized authentication provider. I already found a hint, that a field called forcePrincipleAsString might be the reason for my problem, although it should initially be set to false, and the customized authentication provider i use has no such field.
This is my custom authentication provider:
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
public Authentication authenticate(Authentication authentication ) throws AuthenticationException {
String password = authentication.getCredentials().toString().trim();
SecurityUser appUser = new SecurityUser();
return new UsernamePasswordAuthenticationToken(appUser, password, new ArrayList<>());
}
@Override
public boolean supports(Class<? extends Object> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
This is my web security config:
@Configuration
@EnableOAuth2Sso
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan("edu.kit.tm.cm.bamsg.bffweb.iamservice")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String REALM = "bam";
@Autowired
private CustomAuthenticationProvider authProvider;
@Autowired
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.and()
//endpoints without authentication
.authorizeRequests().antMatchers("/logged", "/userData").permitAll()
.and()
// default with authentication
.authorizeRequests().anyRequest().authenticated()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
@Bean
public OAuth2FeignRequestInterceptor oAuth2FeignRequestInterceptor(OAuth2ClientContext context, OAuth2ProtectedResourceDetails details) {
return new OAuth2FeignRequestInterceptor(context, details);
}
// I added this code from an advice, but it didn't help
@Bean
BasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
BasicAuthenticationEntryPoint basicAuth = new BasicAuthenticationEntryPoint();
basicAuth.setRealmName(REALM);
return basicAuth;
}
}
The extended user class looks like that:
public class SecurityUser extends User{
String firstName;
String name;
String password;
private static final long serialVersionUID = 1L;
public SecurityUser() {
super("user", "none", new ArrayList<>());
firstName = "Rainer";
name = "Schlund";
password = "meins";
}
public String getRole(){
return "Student";
}
}
And at least after authentication at the code line with the System.out.println
the customized services should have been called, but unfortunately they are not. Breakpoints in the customized services have never been reached and the principal is still a string and not my customized user:
@ComponentScan("edu.kit.tm.cm.bamsg.bffweb.iamservice")
@RestController
@RequestMapping("/api/theses")
public class ThesisController {
@Autowired
private ThesisClient thesisClient;
@Autowired
private ThesisPersonLinker linker;
@Autowired
private ThesisPersonFilter filter;
@GetMapping
@PreAuthorize("hasRole('theses')")
public ResponseEntity<Collection<ThesisFrontendDTO>> findAllTheses() {
System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal());
The code contains some simplifications for testing like SecurityPerson always returning the same person, but i think that should not be a problem.
Upvotes: 2
Views: 3257
Reputation: 4167
Declaring a CustomAuthenticationProvider
only adds Authentication
object to security context. In order to customize the Principal
object you want in the security context, you will have to implement a UserDetailsService
.
Baeldung is a good primer.
Upvotes: 1