package org.openiot.lsm.utils; import javax.servlet.ServletContext; import org.openiot.commons.util.PropertyManagement; import org.openiot.lsm.http.SecurityInitializer; import org.openiot.security.client.AccessControlUtil; import org.openiot.security.client.AccessTokenExpiredException; import org.openiot.security.client.OAuthorizationCredentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Note that LSM server wants to verify a permission on a service other than LSM itself, it must * have the "ext:retrieve_permissions" permission on that service. For example, if LSM wants to * check if the provided token has permissions for adding Roles, LSM must have the * "ext:retrieve_permissions" on "openiot-security-manager-app" service. */ public class SecurityUtil { private static Logger logger = LoggerFactory.getLogger(SecurityUtil.class); private static final String CREDENTIALS = "OAuthCredentials"; private static final int EXPIRY_CHECK_INTERVAL = 5 * 60 * 1000; // some sample value private static String username; private static String password; private static AccessControlUtil acUtil = AccessControlUtil.getRestInstance("lsm-server"); private static long lastExpiryCheck = 0; static { PropertyManagement props = new PropertyManagement(); username = props.getProperty(SecurityInitializer.LSM_SERVER_USERNAME, "lsmuser"); password = props.getProperty(SecurityInitializer.LSM_SERVER_PASSWORD, "lsmuserpass"); } public static boolean hasPermission(String perm, ServletContext context, String accessToken, String clientId) { return hasPermission(perm, context, accessToken, clientId, true); } /** * @param perm * the permission string to be checked * @param context * @param accessToken * the access token of the requester * @param clientId * the clientId of the requester * @param lsmIsTarget * if true, it is checked if <code>accessToken</code> has the permission * <code>perm</code> on LSM. Otherwise, it is checked if <code>accessToken</code> has * the permission <code>perm</code> on the service specified by the <code>clientId. * @return */ public static boolean hasPermission(String perm, ServletContext context, String accessToken, String clientId, boolean lsmIsTarget) { OAuthorizationCredentials credentials = (OAuthorizationCredentials) context.getAttribute(CREDENTIALS); if (credentials == null) { credentials = login(context); } if (credentials != null) { try { OAuthorizationCredentials callerCredentials = new OAuthorizationCredentials(accessToken, clientId, null); OAuthorizationCredentials credentialsToTest = new OAuthorizationCredentials(credentials.getAccessToken(), credentials.getClientId(), callerCredentials); boolean hasPermission; if (lsmIsTarget) hasPermission = acUtil.hasPermission(perm, credentialsToTest); else hasPermission = acUtil.hasPermission(perm, clientId, credentialsToTest); if (acUtil.getAuthorizationManager().isCachingEnabled()) { // check if the LSM access token has expired (this step should be done only if // caching is enabled) if (System.currentTimeMillis() - lastExpiryCheck > EXPIRY_CHECK_INTERVAL) { logger.debug("Checking if LSM access token is expired"); String expiredAT = acUtil.getExpiredAccessToken(credentialsToTest); lastExpiryCheck = System.currentTimeMillis(); if (credentials.getAccessToken().equals(expiredAT)) { // LSM access token has expired logger.debug("LSM access token has expired. Attempting to log in CAS."); context.setAttribute(CREDENTIALS, null); return hasPermission(perm, context, accessToken, clientId); } else if (accessToken.equals(expiredAT)) { // The access token of the requester is expired logger.debug("The access token of the requester has expired: {} ", expiredAT); return false; } } } return hasPermission; } catch (AccessTokenExpiredException e) { if (e.getToken().equals(credentials.getAccessToken())) { // LSM access token has expired logger.debug("LSM access token has expired. Attempting to log in CAS."); context.setAttribute(CREDENTIALS, null); return hasPermission(perm, context, accessToken, clientId, lsmIsTarget); } } } return false; } public static synchronized OAuthorizationCredentials login(ServletContext context) { OAuthorizationCredentials credentials = (OAuthorizationCredentials) context.getAttribute(CREDENTIALS); if (credentials == null) { logger.debug("Logging into CAS by username {}", username); credentials = acUtil.login(username, password); logger.debug("Credentials obtained after logging in is {}", credentials); context.setAttribute(CREDENTIALS, credentials); lastExpiryCheck = System.currentTimeMillis(); } else { logger.debug("Credentials found in context. Aborting login process."); } return credentials; } }