} catch (Throwable t) {
logger.error("Invalid social callback", t);
return Flows.forms(session, null, null, uriInfo).setError("Unexpected callback").createErrorPage();
}
String providerId = clientSession.getNote("social_provider");
SocialProvider provider = SocialLoader.load(providerId);
String authMethod = "social@" + provider.getId();
RealmModel realm = clientSession.getRealm();
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder()
.event(EventType.LOGIN)
.client(clientSession.getClient())
.detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
.detail(Details.AUTH_METHOD, authMethod);
if (!realm.isEnabled()) {
event.error(Errors.REALM_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Realm not enabled.");
}
String key = realm.getSocialConfig().get(provider.getId() + ".key");
String secret = realm.getSocialConfig().get(provider.getId() + ".secret");
String callbackUri = Urls.socialCallback(uriInfo.getBaseUri()).toString();
SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri);
Map<String, String[]> queryParams = getQueryParams();
AuthCallback callback = new AuthCallback(queryParams);
SocialUser socialUser;
try {
socialUser = provider.processCallback(clientSession, config, callback);
} catch (SocialAccessDeniedException e) {
event.error(Errors.REJECTED_BY_USER);
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE);
return Flows.forms(session, realm, clientSession.getClient(), uriInfo).setClientSessionCode(clientCode.getCode()).setWarning("Access denied").createLogin();
} catch (SocialProviderException e) {
logger.error("Failed to process social callback", e);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Failed to process social callback");
}
event.detail(Details.USERNAME, socialUser.getId() + "@" + provider.getId());
try {
SocialLinkModel socialLink = new SocialLinkModel(provider.getId(), socialUser.getId(), socialUser.getUsername());
UserModel user = session.users().getUserBySocialLink(socialLink, realm);
// Check if user is already authenticated (this means linking social into existing user account)
if (clientSession.getUserSession() != null) {
UserModel authenticatedUser = clientSession.getUserSession().getUser();
event.event(EventType.SOCIAL_LINK).user(authenticatedUser.getId());
if (user != null) {
event.error(Errors.SOCIAL_ID_IN_USE);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "This social account is already linked to other user");
}
if (!authenticatedUser.isEnabled()) {
event.error(Errors.USER_DISABLED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "User is disabled");
}
if (!authenticatedUser.hasRole(realm.getApplicationByName(Constants.ACCOUNT_MANAGEMENT_APP).getRole(AccountRoles.MANAGE_ACCOUNT))) {
event.error(Errors.NOT_ALLOWED);
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Insufficient permissions to link social account");
}
session.users().addSocialLink(realm, authenticatedUser, socialLink);
logger.debugv("Social provider {0} linked with user {1}", provider.getId(), authenticatedUser.getUsername());
event.success();
return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
}
if (user == null) {
user = session.users().addUser(realm, KeycloakModelUtils.generateId());
user.setEnabled(true);
user.setFirstName(socialUser.getFirstName());
user.setLastName(socialUser.getLastName());
user.setEmail(socialUser.getEmail());
if (realm.isUpdateProfileOnInitialSocialLogin()) {
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE);
}
session.users().addSocialLink(realm, user, socialLink);
event.clone().user(user).event(EventType.REGISTER)
.detail(Details.REGISTER_METHOD, "social@" + provider.getId())
.detail(Details.EMAIL, socialUser.getEmail())
.removeDetail("auth_method")
.success();
}