package eu.dnetlib.functionality.modular.ui.users; import java.net.URLDecoder; import java.security.KeyFactory; import java.security.PublicKey; import java.security.Signature; import java.security.spec.KeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Required; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import com.google.gson.Gson; public class SimpleSSOAuthorizationManager implements AuthorizationManager { private static final Log log = LogFactory.getLog(SimpleSSOAuthorizationManager.class); private Resource pubKeyFile = new ClassPathResource("/eu/dnetlib/functionality/modular/ui/users/pubkey.der"); private String pubKeyAlgo = "RSA"; private String signatureAlgo = "SHA1withRSA"; private PublicKey publicKey; private AuthorizationDAO authorizationDAO; private String defaultSuperAdmin; @Override public User obtainUserDetails(final HttpServletRequest request) { if (request.getCookies() != null) { for (Cookie cookie : request.getCookies()) { if (cookie.getName().equalsIgnoreCase("rinfra-user")) { try { return processCookie(cookie.getValue()); } catch (Exception e) { log.error("Error processing cookie: " + cookie.getValue(), e); return null; } } } } return null; } private User processCookie(final String s) throws Exception { if (s == null || s.isEmpty()) { return null; } final Gson gson = new Gson(); final Map map = gson.fromJson(new String(Base64.decodeBase64(URLDecoder.decode(s.trim(), "UTF-8"))), Map.class); final String message = (String) map.get("payload"); final String signature = (String) map.get("signature"); if (isValidMessage(message, signature)) { final Map userMap = gson.fromJson(message, Map.class); if (userMap.containsKey("uid")) { final String uid = (String) userMap.get("uid"); final User user = new User(uid); user.setEmail((String) userMap.get("email")); user.setFullname(userMap.containsKey("fullname") ? (String) userMap.get("fullname") : uid); user.setPermissionLevels(authorizationDAO.getPermissionLevels(uid)); if (isDefaultSuperAdmin(uid)) { user.getPermissionLevels().add(PermissionLevel.SUPER_ADMIN); } return user; } } return null; } private boolean isDefaultSuperAdmin(final String uid) { return (uid != null && !uid.isEmpty() && uid.equals(getDefaultSuperAdmin())); } protected boolean isValidMessage(final String message, final String signature) { log.info("checking message " + message + " with sig " + signature); if (message == null || message.isEmpty() || signature == null || signature.isEmpty()) { log.error("Null or empty values in message or signature"); return false; } try { final Signature sg = Signature.getInstance(getSignatureAlgo()); sg.initVerify(getPublicKey()); sg.update(message.getBytes()); return sg.verify(Hex.decodeHex(signature.toCharArray())); } catch(Exception e) { log.error("Error verifyng signature", e); return false; } } public void init() throws Exception { final byte[] keyBytes = IOUtils.toByteArray(getPubKeyFile().getInputStream()); final KeySpec spec = new X509EncodedKeySpec(keyBytes); setPublicKey(KeyFactory.getInstance(getPubKeyAlgo()).generatePublic(spec)); } public Resource getPubKeyFile() { return pubKeyFile; } @Required public void setPubKeyFile(Resource pubKeyFile) { this.pubKeyFile = pubKeyFile; } public String getPubKeyAlgo() { return pubKeyAlgo; } @Required public void setPubKeyAlgo(String pubKeyAlgo) { this.pubKeyAlgo = pubKeyAlgo; } public String getSignatureAlgo() { return signatureAlgo; } @Required public void setSignatureAlgo(String signatureAlgo) { this.signatureAlgo = signatureAlgo; } public PublicKey getPublicKey() { return publicKey; } public void setPublicKey(PublicKey publicKey) { this.publicKey = publicKey; } public AuthorizationDAO getAuthorizationDAO() { return authorizationDAO; } @Required public void setAuthorizationDAO(AuthorizationDAO authorizationDAO) { this.authorizationDAO = authorizationDAO; } public String getDefaultSuperAdmin() { return defaultSuperAdmin; } @Required public void setDefaultSuperAdmin(String defaultSuperAdmin) { this.defaultSuperAdmin = defaultSuperAdmin; } }