Commit fe5aa708 by Tuomas Riihimäki

Argh.. New payara does not allow realm to modify the username (ie add domain, or…

… change login when using rest auth
1 parent 683dce59
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
*/ */
package fi.codecrew.moya; package fi.codecrew.moya;
public class AuthenticationResult { import java.io.Serializable;
public class AuthenticationResult implements Serializable {
private String username = null; private String username = null;
private String usertype = null; private String usertype = null;
......
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>moya-authmodule</artifactId> <artifactId>moya-authmodule</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.glassfish.main.security</groupId> <groupId>org.glassfish.main.security</groupId>
......
...@@ -35,4 +35,6 @@ public interface ApiApplicationBeanLocal { ...@@ -35,4 +35,6 @@ public interface ApiApplicationBeanLocal {
ApiApplicationInstance createApplicationInstance(ApiApplication application); ApiApplicationInstance createApplicationInstance(ApiApplication application);
ApiApplication findApplication(String appKey); ApiApplication findApplication(String appKey);
String findUsernameForApikey(String appkey, String userkey, String domain);
} }
...@@ -25,6 +25,7 @@ import java.util.List; ...@@ -25,6 +25,7 @@ import java.util.List;
import javax.annotation.security.DeclareRoles; import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed; import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.LocalBean; import javax.ejb.LocalBean;
import javax.ejb.Singleton; import javax.ejb.Singleton;
...@@ -114,6 +115,27 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal { ...@@ -114,6 +115,27 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal {
return applicationFacade.findByAppid(appKey); return applicationFacade.findByAppid(appKey);
} }
/**
* Note that this function can sould be allowed to be called without principal, ie without domain information.
*
* @param appkey
* @param userkey
* @param domain
* @return
*/
@Override
public String findUsernameForApikey(String appkey, String userkey, String domain) {
LanEvent event = eventBean.getEventForHostname(domain);
if (event == null) {
throw new EJBException("Event not found for domain: " + domain);
}
ApiApplicationInstance instance = instanceFacade.findInstance(appkey, userkey, event);
if (instance == null) {
throw new EJBException("ApiApplicationInstance not found");
}
return instance.getEventuser().getUser().getLogin();
}
@Override @Override
@RolesAllowed(SpecialPermission.S_USER) @RolesAllowed(SpecialPermission.S_USER)
public List<ApiApplication> findMyApplications() { public List<ApiApplication> findMyApplications() {
......
...@@ -174,6 +174,9 @@ public class PermissionBean implements PermissionBeanLocal { ...@@ -174,6 +174,9 @@ public class PermissionBean implements PermissionBeanLocal {
@Override @Override
public EventUser getCurrentUser() { public EventUser getCurrentUser() {
LanEvent event = eventbean.getEventForHostname(getPrincipalDomain()); LanEvent event = eventbean.getEventForHostname(getPrincipalDomain());
if (event == null) {
throw new EJBException("Could not find event for current user");
}
EventUser ret = eventUserFacade.findByLogin(getPrincipalName(), event); EventUser ret = eventUserFacade.findByLogin(getPrincipalName(), event);
if (ret == null) { if (ret == null) {
ret = getAnonEventUser(); ret = getAnonEventUser();
......
...@@ -38,31 +38,37 @@ public class BasicAuthPBean extends ApiAuth implements AuthenticationFormat { ...@@ -38,31 +38,37 @@ public class BasicAuthPBean extends ApiAuth implements AuthenticationFormat {
/** /**
* Authenticate application with username being `null` and password containing basic auth credentials: * 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: `:` * username should be constant 'appauth' and password should contain the following fields delimited by: `:`
* 1) application Id * 1) application Id
* 2) application instance authname * 2) application instance authname
* 3) application instance secret * 3) application instance secret
*
*/ */
@Override @Override
public AuthenticationResult authenticate(String jaasUsername, String password) { public AuthenticationResult authenticate(final String username, final String password) {
AuthenticationResult ret = null; AuthenticationResult ret = null;
String username = UserLoginUtils.getUsernameFromJaasString(jaasUsername); //String username = UserLoginUtils.getUsernameFromJaasString(jaasUsername);
String domain = UserLoginUtils.getDomainFromJaasString(jaasUsername);
LanEvent event = eventbean.getEventForHostname(domain);
if ((username == null || username.isEmpty()) && password.startsWith(HEADER_PREFIX)) { if (password.startsWith(HEADER_PREFIX)) {
ret = new AuthenticationResult(); ret = new AuthenticationResult();
ret.setUsertype(UserType.REST.name()); ret.setUsertype(UserType.REST.name());
try { try {
String domain = UserLoginUtils.getDomainFromJaasString(username);
LanEvent event = eventbean.getEventForHostname(domain);
String[] pwdsplit = password.split(" "); String[] pwdsplit = password.split(" ");
if (pwdsplit.length != 2) { if (pwdsplit.length != 2) {
logger.warn("Rest auth with Basic failed because pwdsplit != 2: user '{}', password '{}'", username, logger.warn("Rest auth with Basic failed because pwdsplit != 2: user '{}''", username );
password); 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; return null;
} }
String authStr = new String(Base64.getDecoder().decode(pwdsplit[1]), UTF8);
String[] splitStr = authStr.split(PASSWORD_DELIMITER); String[] splitStr = authStr.split(PASSWORD_DELIMITER);
if (splitStr.length != 4 || !PASSWORD_PREFIX.equals(splitStr[0])) { if (splitStr.length != 4 || !PASSWORD_PREFIX.equals(splitStr[0])) {
logger.warn( logger.warn(
...@@ -76,11 +82,11 @@ public class BasicAuthPBean extends ApiAuth implements AuthenticationFormat { ...@@ -76,11 +82,11 @@ public class BasicAuthPBean extends ApiAuth implements AuthenticationFormat {
ApiApplicationInstance appInstance = verifyAppInstance(appId, userId, event); ApiApplicationInstance appInstance = verifyAppInstance(appId, userId, event);
if (appInstance != null && appKey != null && !appKey.isEmpty() && appKey.equals(appInstance.getSecretKey())) { if (appInstance != null && appKey != null && !appKey.isEmpty() && appKey.equals(appInstance.getSecretKey())) {
ret.setUsername(getUsername(appInstance) + '@' + domain); ret.setUsername(username);
} }
} catch (Exception e) { } catch (Exception e) {
ret = null;
logger.warn("Invalid base64 string on Rest Basic auth: " + password, e); logger.warn("Invalid base64 string on Rest Basic auth: " + password, e);
} }
} }
return ret; return ret;
......
...@@ -35,7 +35,10 @@ public class RestMacAuthPBean extends ApiAuth implements AuthenticationFormat { ...@@ -35,7 +35,10 @@ public class RestMacAuthPBean extends ApiAuth implements AuthenticationFormat {
if ((username == null || username.isEmpty()) && password.startsWith(JaasBeanLocal.REST_PREFIX)) { if ((username == null || username.isEmpty()) && password.startsWith(JaasBeanLocal.REST_PREFIX)) {
ret = new AuthenticationResult(); ret = new AuthenticationResult();
ret.setUsertype(UserType.REST.name()); ret.setUsertype(UserType.REST.name());
ret.setUsername(restAuth(password, event) + '@'+domain); if(restAuth(password, event) != null) {
ret.setUsername(jaasUsername);
}
//ret.setUsername(restAuth(password, event) + '@'+domain);
} }
return ret; return ret;
} }
......
...@@ -21,6 +21,7 @@ package fi.codecrew.moya; ...@@ -21,6 +21,7 @@ package fi.codecrew.moya;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.Principal; import java.security.Principal;
import java.util.Base64;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.faces.application.ProjectStage; import javax.faces.application.ProjectStage;
...@@ -36,15 +37,12 @@ import javax.servlet.http.HttpServletRequest; ...@@ -36,15 +37,12 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import fi.codecrew.moya.beans.*;
import fi.codecrew.moya.utilities.UserLoginUtils; import fi.codecrew.moya.utilities.UserLoginUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.slf4j.MDC; import org.slf4j.MDC;
import fi.codecrew.moya.beans.JaasBeanLocal;
import fi.codecrew.moya.beans.LoggingBeanLocal;
import fi.codecrew.moya.beans.RestBeanLocal;
import fi.codecrew.moya.beans.SessionMgmtBeanLocal;
import fi.codecrew.moya.clientutils.BortalLocalContextHolder; import fi.codecrew.moya.clientutils.BortalLocalContextHolder;
import fi.codecrew.moya.model.User; import fi.codecrew.moya.model.User;
import fi.codecrew.moya.rest.RestApplicationEntrypoint; import fi.codecrew.moya.rest.RestApplicationEntrypoint;
...@@ -67,6 +65,9 @@ public class HostnameFilter implements Filter { ...@@ -67,6 +65,9 @@ public class HostnameFilter implements Filter {
@EJB @EJB
private LoggingBeanLocal logbean; private LoggingBeanLocal logbean;
@EJB
private ApiApplicationBeanLocal apibean;
@Override @Override
public void init(FilterConfig config) throws ServletException { public void init(FilterConfig config) throws ServletException {
// check if software is in development -mode // check if software is in development -mode
...@@ -170,12 +171,14 @@ public class HostnameFilter implements Filter { ...@@ -170,12 +171,14 @@ public class HostnameFilter implements Filter {
try { try {
httpRequest = (HttpServletRequest) request; httpRequest = (HttpServletRequest) request;
insertServerLoggingContext(httpRequest, authtype); insertServerLoggingContext(httpRequest, authtype);
logger.info("Logging in with username {} and password {}, remote {}, authtype: {}", httpRequest.getUserPrincipal(), httpRequest.getRemoteUser(), httpRequest.getAuthType());
String hostname = parseHostname(httpRequest); String hostname = parseHostname(httpRequest);
if (httpRequest.getUserPrincipal() == null) { if (httpRequest.getUserPrincipal() == null) {
// Check if we are logging in with rest // Check if we are can login in with rest alternative methods ( appkey, basic auth, etc.. )
if (RestApplicationEntrypoint.REST_PATH.equals(httpRequest.getServletPath())) { if (RestApplicationEntrypoint.REST_PATH.equals(httpRequest.getServletPath())
|| "/dydata".equals(httpRequest.getServletPath())) {
authtype = AuthType.REST; authtype = AuthType.REST;
if (!restAuth(httpRequest, response)) { if (!restAuth(httpRequest, response)) {
...@@ -246,12 +249,26 @@ public class HostnameFilter implements Filter { ...@@ -246,12 +249,26 @@ public class HostnameFilter implements Filter {
restAuthStr = httpRequest.getHeader("Authorization"); restAuthStr = httpRequest.getHeader("Authorization");
// } // }
if (restAuthStr == null && httpRequest.getParameter("appkey") != null) { String userkey = null;
String appkey = null;
// Payara got updated, and does not allow changing of username anymore, so we must send
// username and domain to initial jaas-login query...
if (restAuthStr != null) {
String decodedStr = new String(Base64.getDecoder().decode(restAuthStr.split(" ")[1]), UTF8);
String[] splitStr = decodedStr.split(":");
appkey = splitStr[1];
userkey = splitStr[2];
// final String appKey = splitStr[3];
} else if (httpRequest.getParameter("appkey") != null) {
appkey = httpRequest.getParameter("appkey");
userkey = httpRequest.getParameter("appuser");
StringBuilder hashBuilder = new StringBuilder(); StringBuilder hashBuilder = new StringBuilder();
hashBuilder.append(JaasBeanLocal.REST_PREFIX); hashBuilder.append(JaasBeanLocal.REST_PREFIX);
hashBuilder.append(httpRequest.getParameter("appkey")).append(":"); hashBuilder.append(appkey).append(":");
hashBuilder.append(httpRequest.getParameter("appuser")).append(":"); hashBuilder.append(userkey).append(":");
hashBuilder.append(httpRequest.getParameter("appstamp")).append(":"); hashBuilder.append(httpRequest.getParameter("appstamp")).append(":");
hashBuilder.append(httpRequest.getParameter("appmac")).append(":"); hashBuilder.append(httpRequest.getParameter("appmac")).append(":");
hashBuilder.append(httpRequest.getPathInfo()); hashBuilder.append(httpRequest.getPathInfo());
...@@ -259,13 +276,18 @@ public class HostnameFilter implements Filter { ...@@ -259,13 +276,18 @@ public class HostnameFilter implements Filter {
} }
boolean ret = true; boolean ret = true;
String domain = parseHostname(httpRequest);
try { try {
if (restAuthStr == null) { if (restAuthStr == null) {
throw new ServletException("No auth data"); throw new ServletException("No auth data");
} }
final String username = "@" + parseHostname(httpRequest); //final String username = "@" + parseHostname(httpRequest);
logger.info("Logging in with username {} and password {}", username, restAuthStr); String userLogin = apibean.findUsernameForApikey(appkey, userkey, domain);
httpRequest.login(username, restAuthStr); if (userLogin != null) {
httpRequest.login(userLogin + '@' + domain, restAuthStr);
}
Principal p = httpRequest.getUserPrincipal();
logger.warn("Logged in with rest:{}, ", (p == null) ? null : p.getName());
} catch (ServletException loginEx) { } catch (ServletException loginEx) {
ret = false; ret = false;
logger.info("Rest api authentication failed for path " + httpRequest.getPathInfo() + " " logger.info("Rest api authentication failed for path " + httpRequest.getPathInfo() + " "
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!