Issue
I'm trying to add OAuth2 login to an existing form login application. So far I've added the required configuration to get Google auth working and the goal is to enable existing username/password users (or new users) to login both ways.
All my controllers rely on my UserDetails
implementation:
public class User implements UserDetails {
private Long id;
private String email;
private String password;
private String googleAccessToken;
// ...
And I can get the logged user in controllers like this:
@GetMapping
public String index(@AuthenticationPrincipal User user, Model model) {
So what I've done is to implement my custom OAuth2UserService
to fetch the existing user from the database but I can't find the way to set the User
as the principal.
In previous versions of the OAuth2 integration it seemed to exist a simpler solution based on PrincipalExtractor
but it is no longer available.
@Service
@RequiredArgsConstructor
public class OAuth2UserDetailsService implements OAuth2UserService<OidcUserRequest, OidcUser> {
private final UsersRepository usersRepository;
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
final OidcUserService delegate = new OidcUserService();
User user;
// Delegate to the default implementation for loading a user
OidcUser oidcUser = delegate.loadUser(userRequest);
switch (userRequest.getClientRegistration().getClientName()) {
case "google":
user = usersRepository.findOneByGoogleAccessToken(userRequest.getAccessToken());
break;
default:
throw new OAuth2AuthenticationException(new OAuth2Error("invalid_token"));
}
// here I should return my user principal
return new DefaultOidcUser(null, null);
}
Any ideas?
Solution
Finally solved this returning an instance of OidcUser
:
public class UserPrincipal implements UserDetails, OidcUser {
// ...
}
And in the OAuth2UserService
:
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
final OidcUserService delegate = new OidcUserService();
User user;
// Delegate to the default implementation for loading a user
OidcUser oidcUser = delegate.loadUser(userRequest);
// ...
return new UserPrincipal(user, oidcUser);
}
Answered By - Joaquín L. Robles
Answer Checked By - Marilyn (JavaFixing Volunteer)