BasicAuthPBean.java 3.31 KB
package fi.codecrew.moya.beans.auth;

import java.nio.charset.Charset;
import java.util.Base64;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;

import fi.codecrew.moya.beans.EventBean;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.utilities.UserLoginUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fi.codecrew.moya.AuthenticationResult;
import fi.codecrew.moya.beans.JaasBean.UserType;
import fi.codecrew.moya.facade.ApiApplicationFacade;
import fi.codecrew.moya.facade.ApiApplicationInstanceFacade;
import fi.codecrew.moya.model.ApiApplicationInstance;

@LocalBean
@Stateless
public class BasicAuthPBean extends ApiAuth implements AuthenticationFormat {

	private static final String HEADER_PREFIX = "Basic ";
	private static final String PASSWORD_DELIMITER = ":";
	private static final String PASSWORD_PREFIX = "appauth";
	private static final Logger logger = LoggerFactory.getLogger(BasicAuthPBean.class);
	private static final Charset UTF8 = Charset.forName("UTF-8");

	@EJB
	private ApiApplicationFacade appfacade;
	@EJB
	private ApiApplicationInstanceFacade appInstanceFacade;
	@EJB
	private EventBean eventbean;

	/**
	 * Authenticate application with username being `null` and password containing basic auth credentials:
	 * username should be constant 'appauth' and password should contain the following fields delimited by: `:`
	 * 1) application Id
	 * 2) application instance authname
	 * 3) application instance secret
	 */
	@Override
	public AuthenticationResult authenticate(final String username, final String password) {
		AuthenticationResult ret = null;
		//String username = UserLoginUtils.getUsernameFromJaasString(jaasUsername);

		if (password.startsWith(HEADER_PREFIX)) {
			ret = new AuthenticationResult();
			ret.setUsertype(UserType.REST.name());

			try {
				String domain = UserLoginUtils.getDomainFromJaasString(username);
				LanEvent event = eventbean.getEventForHostname(domain);

				String[] pwdsplit = password.split(" ");
				if (pwdsplit.length != 2) {
					logger.warn("Rest auth with Basic failed because pwdsplit != 2: user '{}''", username );
					return null;
				}
				// There is a possibility that user has a password that starts with "Basic ". To combat this,
				// we chech that the authdata is really a base64 string. If not, we continue trying with other methods
				String authStr = null;
				try {
					authStr = new String(Base64.getDecoder().decode(pwdsplit[1]), UTF8);
				} catch (IllegalArgumentException ie) {
					return null;
				}
				String[] splitStr = authStr.split(PASSWORD_DELIMITER);
				if (splitStr.length != 4 || !PASSWORD_PREFIX.equals(splitStr[0])) {
					logger.warn(
						"Invalid Basic authentication string '{}'. Authstring must start with {}, followed by appid and app pass",
						authStr, PASSWORD_PREFIX);
					return null;
				}
				final String appId = splitStr[1];
				final String userId = splitStr[2];
				final String appKey = splitStr[3];

				ApiApplicationInstance appInstance = verifyAppInstance(appId, userId, event);
				if (appInstance != null && appKey != null && !appKey.isEmpty() && appKey.equals(appInstance.getSecretKey())) {
					ret.setUsername(username);
				}
			} catch (Exception e) {
				ret = null;
				logger.warn("Invalid base64 string on Rest Basic auth: " + password, e);
			}
		}
		return ret;
	}

}