Social login experiences higher click rates due to its convenience, and we aim to retain both the username and email in our system to track user logins and link identities to other user activities, such as PTE question answering.
In the answer module, Richard has accomplished a significant amount of work, which is truly impressive! Richard placed the answer module within the Authentication Server. However, we need to transfer it to the PTE Resource Server and utilize the userId for connecting the two microservices.
The existing code provides two entry points for implementing this functionality. One is the AuthenticationSuccessHandler
, and the other is the OAuth2UserService
. The former serves as a callback function whenever the user is successfully authenticated, while the latter is a user repository specialized for OAuth2
users. Regular users utilize the UserService
.
Upon further investigation, we discovered that users logging in via Google Social Login portals are Oidc users rather than OAuth2 users, which may be the reason for the discrepancy. Subsequently, we confirm that Google calls the OidcUserService
and the user type is OidcUser
, while Github calls DefaultOAuth2UserService
, and the user type is OAuth2User
. Thus, we have successfully created a function to save the user.
DefaultOAuth2UserService
and OIDCUserService
implement OAuth2UserService<OAuth2UserRequest, OAuth2User>
and OAuth2UserService<OidcUserRequest, OidcUser>
respectively.
We have extracted the common code to enhance conciseness and facilitate better code maintenance.
public class MNUserUtil {
public static void processOAuthUser(MNUserRepository userRepo,
MNRoleRepository roleRepo,
OAuth2User oauthUser,
String clientId) {
String email = oauthUser.getAttribute("email");
String name = oauthUser.getAttribute("name");
String username = name.trim().toLowerCase().replace(" ", "_");
if (userRepo.findByEmail(email).isEmpty()) {
MNUser user = new MNUser();
user.setEmail(email);
user.setVerified(true);
user.setName(name);
MNRole userRole = roleRepo.findByName(MNRoleEnum.ROLE_USER.name()).get();
user.setRoles(new HashSet<>(Collections.singletonList(userRole)));
user.setProviderId(clientId);
if (userRepo.findByUsername(username).isEmpty()) {
user.setUsername(username);
} else {
do {
username = MNRandomUtil.randomString(8);
} while (!userRepo.findByUsername(username).isEmpty());
}
userRepo.save(user);
}
}
}
@Service
public class MNUserServiceOIDC extends OidcUserService {
private MNUserRepository userRepo;
@Autowired
public void setMNUserRepository(MNUserRepository mnUserRepository) {
this.userRepo = mnUserRepository;
}
private MNRoleRepository roleRepo;
@Autowired
public void setMNRoleRepository(MNRoleRepository mnRoleRepository) {
this.roleRepo = mnRoleRepository;
}
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
OidcUser oidcUser = super.loadUser(userRequest);
String clientId = userRequest.getClientRegistration().getRegistrationId();
MNUserUtil.processOAuthUser(userRepo, roleRepo, oidcUser, clientId);
return oidcUser;
}
}
@Service
public class MNUserServiceOAuth2 extends DefaultOAuth2UserService {
private MNUserRepository userRepo;
@Autowired
public void setMNUserRepository(MNUserRepository mnUserRepository) {
this.userRepo = mnUserRepository;
}
private MNRoleRepository roleRepo;
@Autowired
public void setMNRoleRepository(MNRoleRepository mnRoleRepository) {
this.roleRepo = mnRoleRepository;
}
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oauthUser = super.loadUser(userRequest);
String clientId = userRequest.getClientRegistration().getRegistrationId();
MNUserUtil.processOAuthUser(userRepo, roleRepo, oauthUser, clientId);
return new MNUserOAuth2(oauthUser);
}
}