254 lines
11 KiB
Java
254 lines
11 KiB
Java
package org.gcube.portal.oidc.lr62;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.util.Arrays;
|
|
import java.util.Calendar;
|
|
import java.util.Locale;
|
|
import java.util.UUID;
|
|
|
|
import javax.imageio.ImageIO;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
import org.gcube.oidc.URLEncodedContextMapper;
|
|
import org.gcube.oidc.rest.JWTToken;
|
|
import org.gcube.oidc.rest.OpenIdConnectRESTHelper;
|
|
|
|
import com.liferay.portal.kernel.exception.PortalException;
|
|
import com.liferay.portal.kernel.exception.SystemException;
|
|
import com.liferay.portal.kernel.log.Log;
|
|
import com.liferay.portal.kernel.log.LogFactoryUtil;
|
|
import com.liferay.portal.kernel.util.LocaleUtil;
|
|
import com.liferay.portal.kernel.util.StringPool;
|
|
import com.liferay.portal.model.User;
|
|
import com.liferay.portal.security.auth.BaseAutoLogin;
|
|
import com.liferay.portal.service.ServiceContext;
|
|
import com.liferay.portal.service.UserLocalServiceUtil;
|
|
import com.liferay.portal.util.PortalUtil;
|
|
import com.liferay.util.PwdGenerator;
|
|
|
|
public class OpenIdConnectAutoLogin extends BaseAutoLogin {
|
|
|
|
private static final Log log = LogFactoryUtil.getLog(OpenIdConnectAutoLogin.class);
|
|
|
|
private static final boolean ASSURE_AVATAR_FORMAT = true;
|
|
private static final String DEFAULT_AVATAR_FORMAT = "png";
|
|
private static final boolean DELETE_AVATAR_IF_NOT_FOUND_ON_SERVER = false;
|
|
|
|
@Override
|
|
public String[] doLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
|
JWTToken token = JWTTokenUtil.getOIDCFromRequest(request);
|
|
if (token == null) {
|
|
if (log.isTraceEnabled()) {
|
|
log.trace("OIDC token is null. Can't perform auto login");
|
|
}
|
|
return null;
|
|
} else {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Perform auto login with OIDC token " + token.getTokenEssentials());
|
|
}
|
|
}
|
|
LiferayOpenIdConnectConfiguration configuration = LiferayOpenIdConnectConfiguration.getConfiguration(request);
|
|
long companyId = PortalUtil.getCompanyId(request);
|
|
long groupId = PortalUtil.getScopeGroupId(request);
|
|
String portalURL = PortalUtil.getPortalURL(request, true);
|
|
User user = createOrUpdateUser(token, companyId, groupId, portalURL, configuration);
|
|
if (user != null) {
|
|
log.info("Applying sites and roles strategy");
|
|
try {
|
|
UserSitesToGroupsAndRolesMapper mapper = new UserSitesToGroupsAndRolesMapper(
|
|
user, new URLEncodedContextMapper(
|
|
token.getResourceNameToAccessRolesMap(Arrays.asList(JWTToken.ACCOUNT_RESOURCE))));
|
|
|
|
mapper.map();
|
|
} catch (Throwable t) {
|
|
// TODO: to be removed when tested in depth
|
|
log.error("Applying strategy", t);
|
|
}
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Returning logged in user's info");
|
|
}
|
|
return new String[] { String.valueOf(user.getUserId()), UUID.randomUUID().toString(), "false" };
|
|
} else {
|
|
log.warn("User is null");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static User createOrUpdateUser(JWTToken token, long companyId, long groupId, String portalURL,
|
|
LiferayOpenIdConnectConfiguration configuration) throws Exception {
|
|
|
|
String username = token.getUserName();
|
|
String email = token.getEmail();
|
|
String given = token.getGiven();
|
|
String family = token.getFamily();
|
|
String subject = token.getSub();
|
|
User user = null;
|
|
try {
|
|
user = UserLocalServiceUtil.fetchUserByScreenName(companyId, username);
|
|
if (user == null) {
|
|
// Then search by openId, in case an admin changed the username on OIDC server
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("No Liferay user found with username=" + username + ", trying with openId");
|
|
}
|
|
user = UserLocalServiceUtil.fetchUserByOpenId(companyId, subject);
|
|
if (user == null) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("No Liferay user found with openid=" + subject + " and email address=" + email);
|
|
}
|
|
if (configuration.createUnexistingUser()) {
|
|
log.info("A new user will be created [email=" + email + ",given=" + given + ",family=" + family
|
|
+ ",subject=" + subject + ",username=" + username);
|
|
|
|
user = addUser(companyId, groupId, portalURL, email, given, family, subject, username);
|
|
} else {
|
|
log.warn("Unexisting user will not be created according to configuration");
|
|
return null;
|
|
}
|
|
} else if (log.isDebugEnabled()) {
|
|
log.debug("User found by its openId, other info will be updated");
|
|
}
|
|
}
|
|
boolean updateUser = false;
|
|
if (user != null) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("User found, checking its details against userinfo for changes");
|
|
}
|
|
if (given != null && !given.equals(user.getFirstName())) {
|
|
if (log.isTraceEnabled()) {
|
|
log.trace("Given name is changed");
|
|
}
|
|
user.setFirstName(given);
|
|
updateUser = true;
|
|
}
|
|
if (family != null && !family.equals(user.getLastName())) {
|
|
if (log.isTraceEnabled()) {
|
|
log.trace("Last name is changed");
|
|
}
|
|
user.setLastName(family);
|
|
updateUser = true;
|
|
}
|
|
if (email != null && !email.equals(user.getEmailAddress())) {
|
|
if (log.isTraceEnabled()) {
|
|
log.trace("Email address is changed");
|
|
}
|
|
user.setEmailAddress(email);
|
|
updateUser = true;
|
|
}
|
|
if (subject != null && !subject.equals(user.getOpenId())) {
|
|
if (log.isTraceEnabled()) {
|
|
log.trace("Setting OOID subject as openid");
|
|
}
|
|
user.setOpenId(subject);
|
|
updateUser = true;
|
|
}
|
|
}
|
|
if (updateUser) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Updating user's details with info from userinfo");
|
|
}
|
|
UserLocalServiceUtil.updateUser(user);
|
|
}
|
|
|
|
try {
|
|
byte[] userAvatar = OpenIdConnectRESTHelper.getUserAvatar(configuration.getAvatarURL(), token);
|
|
if (userAvatar != null && userAvatar.length > 0) {
|
|
if (ASSURE_AVATAR_FORMAT) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Assuring avatar image format as: " + DEFAULT_AVATAR_FORMAT);
|
|
log.debug("Reading image stream with length: " + userAvatar.length);
|
|
}
|
|
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(userAvatar));
|
|
if (bi != null) {
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Converting avatar stream image format to: " + DEFAULT_AVATAR_FORMAT);
|
|
}
|
|
ImageIO.write(bi, DEFAULT_AVATAR_FORMAT, baos);
|
|
baos.flush();
|
|
baos.close();
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Reading converted image from the BAOS");
|
|
}
|
|
userAvatar = baos.toByteArray();
|
|
} else {
|
|
log.warn("Buffered image read is null!");
|
|
}
|
|
}
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Saving the retrieved avatar as user's portrait");
|
|
}
|
|
UserLocalServiceUtil.updatePortrait(user.getUserId(), userAvatar);
|
|
} else if (DELETE_AVATAR_IF_NOT_FOUND_ON_SERVER) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Deleting the user's portrait since no avatar has been found for the user");
|
|
}
|
|
UserLocalServiceUtil.deletePortrait(user.getUserId());
|
|
}
|
|
} catch (Throwable t) {
|
|
log.error("Cannot save/update/delete user's portrait", t);
|
|
}
|
|
} catch (SystemException | PortalException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return user;
|
|
}
|
|
|
|
public static User addUser(long companyId, long groupId, String portalURL, String emailAddress, String firstName,
|
|
String lastName, String openid, String username) throws SystemException, PortalException {
|
|
|
|
Locale locale = LocaleUtil.getMostRelevantLocale();
|
|
long creatorUserId = 0;
|
|
boolean autoPassword = false;
|
|
String password1 = PwdGenerator.getPassword();
|
|
String password2 = password1;
|
|
boolean autoScreenName = username == null;
|
|
String screenName = StringPool.BLANK;
|
|
if (autoScreenName) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Screen name will be auto-generated");
|
|
}
|
|
} else {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("Screen name will be set to: " + username);
|
|
}
|
|
screenName = username;
|
|
}
|
|
long facebookId = 0;
|
|
String openId = openid;
|
|
String middleName = StringPool.BLANK;
|
|
int prefixId = 0;
|
|
int suffixId = 0;
|
|
boolean male = true;
|
|
int birthdayMonth = Calendar.JANUARY;
|
|
int birthdayDay = 1;
|
|
int birthdayYear = 1970;
|
|
String jobTitle = StringPool.BLANK;
|
|
long[] groupIds = null;
|
|
long[] organizationIds = null;
|
|
long[] roleIds = null;
|
|
long[] userGroupIds = null;
|
|
boolean sendEmail = false;
|
|
ServiceContext serviceContext = new ServiceContext();
|
|
serviceContext.setScopeGroupId(groupId);
|
|
serviceContext.setPortalURL(portalURL);
|
|
|
|
User user = UserLocalServiceUtil.addUser(creatorUserId, companyId, autoPassword, password1, password2,
|
|
autoScreenName, screenName, emailAddress, facebookId, openId, locale, firstName, middleName, lastName,
|
|
prefixId, suffixId, male, birthdayMonth, birthdayDay, birthdayYear, jobTitle, groupIds, organizationIds,
|
|
roleIds, userGroupIds, sendEmail, serviceContext);
|
|
|
|
// No password
|
|
user.setPasswordReset(false);
|
|
// email is already verified by oidc provider
|
|
user.setEmailAddressVerified(true);
|
|
// No reminder query at first login.
|
|
user.setReminderQueryQuestion("x");
|
|
user.setReminderQueryAnswer("y");
|
|
UserLocalServiceUtil.updateUser(user);
|
|
return user;
|
|
}
|
|
|
|
} |