Commit 9ee97728 authored by Roman S's avatar Roman S

Merge pull request #363 from totalscoccia/master

RestAPI Plugin - Provide the possibility to use Custom Auth Filter
parents 12f5bd54 ce10f45a
...@@ -77,7 +77,7 @@ public class AuthFilter implements ContainerRequestFilter { ...@@ -77,7 +77,7 @@ public class AuthFilter implements ContainerRequestFilter {
} }
// HTTP Basic Auth or Shared Secret key // HTTP Basic Auth or Shared Secret key
if (plugin.isHttpBasicAuth()) { if ("basic".equals(plugin.getHttpAuth())) {
String[] usernameAndPassword = BasicAuth.decode(auth); String[] usernameAndPassword = BasicAuth.decode(auth);
// If username or password fail // If username or password fail
......
...@@ -39,6 +39,8 @@ import org.jivesoftware.util.PropertyEventDispatcher; ...@@ -39,6 +39,8 @@ import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener; import org.jivesoftware.util.PropertyEventListener;
import org.jivesoftware.util.StringUtils; import org.jivesoftware.util.StringUtils;
import org.jivesoftware.openfire.plugin.rest.service.JerseyWrapper;
/** /**
* The Class RESTServicePlugin. * The Class RESTServicePlugin.
*/ */
...@@ -47,6 +49,8 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -47,6 +49,8 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
/** The Constant INSTANCE. */ /** The Constant INSTANCE. */
public static final RESTServicePlugin INSTANCE = new RESTServicePlugin(); public static final RESTServicePlugin INSTANCE = new RESTServicePlugin();
private static final String CUSTOM_AUTH_FILTER_PROPERTY_NAME = "plugin.restapi.customAuthFilter";
/** The secret. */ /** The secret. */
private String secret; private String secret;
...@@ -56,8 +60,12 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -56,8 +60,12 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
/** The enabled. */ /** The enabled. */
private boolean enabled; private boolean enabled;
/** The http basic auth. */ /** The http auth. */
private boolean httpBasicAuth; private String httpAuth;
/** The custom authentication filter */
private String customAuthFilterClassName;
/** /**
* Gets the single instance of RESTServicePlugin. * Gets the single instance of RESTServicePlugin.
...@@ -78,12 +86,15 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -78,12 +86,15 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
secret = StringUtils.randomString(16); secret = StringUtils.randomString(16);
setSecret(secret); setSecret(secret);
} }
// See if Custom authentication filter has been defined
customAuthFilterClassName = JiveGlobals.getProperty("plugin.restapi.customAuthFilter", "");
// See if the service is enabled or not. // See if the service is enabled or not.
enabled = JiveGlobals.getBooleanProperty("plugin.restapi.enabled", false); enabled = JiveGlobals.getBooleanProperty("plugin.restapi.enabled", false);
// See if the HTTP Basic Auth is enabled or not. // See if the HTTP Basic Auth is enabled or not.
httpBasicAuth = JiveGlobals.getBooleanProperty("plugin.restapi.httpAuth.enabled", false); httpAuth = JiveGlobals.getProperty("plugin.restapi.httpAuth", "basic");
// Get the list of IP addresses that can use this service. An empty list // Get the list of IP addresses that can use this service. An empty list
// means that this filter is disabled. // means that this filter is disabled.
...@@ -181,6 +192,23 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -181,6 +192,23 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
} }
} }
/**
* Returns the loading status message.
*
* @return the loading status message.
*/
public String getLoadingStatusMessage() {
return JerseyWrapper.getLoadingStatusMessage();
}
/**
* Reloads the Jersey wrapper.
*/
public String loadAuthenticationFilter(String customAuthFilterClassName) {
return JerseyWrapper.tryLoadingAuthenticationFilter(customAuthFilterClassName);
}
/** /**
* Returns the secret key that only valid requests should know. * Returns the secret key that only valid requests should know.
* *
...@@ -201,6 +229,26 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -201,6 +229,26 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
this.secret = secret; this.secret = secret;
} }
/**
* Returns the custom authentication filter class name used in place of the basic ones to grant permission to use the Rest services.
*
* @return custom authentication filter class name .
*/
public String getCustomAuthFilterClassName() {
return customAuthFilterClassName;
}
/**
* Sets the customAuthFIlterClassName used to grant permission to use the Rest services.
*
* @param customAuthFilterClassName
* custom authentication filter class name.
*/
public void setCustomAuthFiIterClassName(String customAuthFilterClassName) {
JiveGlobals.setProperty(CUSTOM_AUTH_FILTER_PROPERTY_NAME, customAuthFilterClassName);
this.customAuthFilterClassName = customAuthFilterClassName;
}
/** /**
* Gets the allowed i ps. * Gets the allowed i ps.
* *
...@@ -243,22 +291,22 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -243,22 +291,22 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
} }
/** /**
* Checks if is http basic auth. * Gets the http authentication mechanism.
* *
* @return true, if is http basic auth * @return the http authentication mechanism
*/ */
public boolean isHttpBasicAuth() { public String getHttpAuth() {
return httpBasicAuth; return httpAuth;
} }
/** /**
* Sets the http basic auth. * Sets the http auth.
* *
* @param httpBasicAuth the new http basic auth * @param httpAuth the new http auth
*/ */
public void setHttpBasicAuth(boolean httpBasicAuth) { public void setHttpAuth(String httpAuth) {
this.httpBasicAuth = httpBasicAuth; this.httpAuth = httpAuth;
JiveGlobals.setProperty("plugin.restapi.httpAuth.enabled", httpBasicAuth ? "true" : "false"); JiveGlobals.setProperty("plugin.restapi.httpAuth", httpAuth);
} }
/* (non-Javadoc) /* (non-Javadoc)
...@@ -271,8 +319,10 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -271,8 +319,10 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
this.enabled = Boolean.parseBoolean((String) params.get("value")); this.enabled = Boolean.parseBoolean((String) params.get("value"));
} else if (property.equals("plugin.restapi.allowedIPs")) { } else if (property.equals("plugin.restapi.allowedIPs")) {
this.allowedIPs = StringUtils.stringToCollection((String) params.get("value")); this.allowedIPs = StringUtils.stringToCollection((String) params.get("value"));
} else if (property.equals("plugin.restapi.httpAuth.enabled")) { } else if (property.equals("plugin.restapi.httpAuth")) {
this.httpBasicAuth = Boolean.parseBoolean((String) params.get("value")); this.httpAuth = (String) params.get("value");
} else if(property.equals(CUSTOM_AUTH_FILTER_PROPERTY_NAME)) {
this.customAuthFilterClassName = (String) params.get("value");
} }
} }
...@@ -286,8 +336,10 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener { ...@@ -286,8 +336,10 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
this.enabled = false; this.enabled = false;
} else if (property.equals("plugin.restapi.allowedIPs")) { } else if (property.equals("plugin.restapi.allowedIPs")) {
this.allowedIPs = Collections.emptyList(); this.allowedIPs = Collections.emptyList();
} else if (property.equals("plugin.restapi.httpAuth.enabled")) { } else if (property.equals("plugin.restapi.httpAuth")) {
this.httpBasicAuth = false; this.httpAuth = "basic";
} else if(property.equals(CUSTOM_AUTH_FILTER_PROPERTY_NAME)) {
this.customAuthFilterClassName = null;
} }
} }
......
<%@ page <%@ page
import="java.util.*, import="java.util.*,
org.jivesoftware.openfire.XMPPServer, org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.util.*,org.jivesoftware.openfire.plugin.rest.RESTServicePlugin" org.jivesoftware.util.*,org.jivesoftware.openfire.plugin.rest.RESTServicePlugin,
org.jivesoftware.openfire.container.Plugin,
org.jivesoftware.openfire.container.PluginManager"
errorPage="error.jsp"%> errorPage="error.jsp"%>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%> <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
...@@ -20,20 +22,45 @@ ...@@ -20,20 +22,45 @@
boolean success = request.getParameter("success") != null; boolean success = request.getParameter("success") != null;
String secret = ParamUtils.getParameter(request, "secret"); String secret = ParamUtils.getParameter(request, "secret");
boolean enabled = ParamUtils.getBooleanParameter(request, "enabled"); boolean enabled = ParamUtils.getBooleanParameter(request, "enabled");
boolean httpBasicAuth = ParamUtils.getBooleanParameter(request, "authtype"); String httpAuth = ParamUtils.getParameter(request, "authtype");
String allowedIPs = ParamUtils.getParameter(request, "allowedIPs"); String allowedIPs = ParamUtils.getParameter(request, "allowedIPs");
String customAuthFilterClassName = ParamUtils.getParameter(request, "customAuthFilterClassName");
String loadingStatus = null;
final PluginManager pluginManager = admin.getXMPPServer().getPluginManager();
RESTServicePlugin plugin = (RESTServicePlugin) XMPPServer.getInstance().getPluginManager() RESTServicePlugin plugin = (RESTServicePlugin) XMPPServer.getInstance().getPluginManager()
.getPlugin("restapi"); .getPlugin("restapi");
// Handle a save // Handle a save
Map errors = new HashMap(); Map errors = new HashMap();
if (save) { if (save) {
if("custom".equals(httpAuth)) {
loadingStatus = plugin.loadAuthenticationFilter(customAuthFilterClassName);
}
if (loadingStatus != null) {
errors.put("loadingStatus", loadingStatus);
}
if (errors.size() == 0) { if (errors.size() == 0) {
boolean is2Reload = "custom".equals(httpAuth) || "custom".equals(plugin.getHttpAuth());
plugin.setEnabled(enabled); plugin.setEnabled(enabled);
plugin.setSecret(secret); plugin.setSecret(secret);
plugin.setHttpBasicAuth(httpBasicAuth); plugin.setHttpAuth(httpAuth);
plugin.setAllowedIPs(StringUtils.stringToCollection(allowedIPs)); plugin.setAllowedIPs(StringUtils.stringToCollection(allowedIPs));
plugin.setCustomAuthFiIterClassName(customAuthFilterClassName);
if(is2Reload) {
String pluginName = pluginManager.getName(plugin);
String pluginDir = pluginManager.getPluginDirectory(plugin).getName();
pluginManager.unloadPlugin(pluginDir);
// Log the event
admin.logEvent("reloaded plugin "+ pluginName, null);
response.sendRedirect("/plugin-admin.jsp?reloadsuccess=true");
}
response.sendRedirect("rest-api.jsp?success=true"); response.sendRedirect("rest-api.jsp?success=true");
return; return;
} }
...@@ -41,8 +68,9 @@ ...@@ -41,8 +68,9 @@
secret = plugin.getSecret(); secret = plugin.getSecret();
enabled = plugin.isEnabled(); enabled = plugin.isEnabled();
httpBasicAuth = plugin.isHttpBasicAuth(); httpAuth = plugin.getHttpAuth();
allowedIPs = StringUtils.collectionToString(plugin.getAllowedIPs()); allowedIPs = StringUtils.collectionToString(plugin.getAllowedIPs());
customAuthFilterClassName = plugin.getCustomAuthFilterClassName();
%> %>
<html> <html>
...@@ -75,7 +103,25 @@ ...@@ -75,7 +103,25 @@
<% <%
} }
%> %>
<%
if (errors.get("loadingStatus") != null) {
%>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/error-16x16.gif"
width="16" height="16" border="0"></td>
<td class="jive-icon-label"><%= loadingStatus %></td>
</tr>
</tbody>
</table>
</div>
<br>
<%
}
%>
<form action="rest-api.jsp?save" method="post"> <form action="rest-api.jsp?save" method="post">
<fieldset> <fieldset>
...@@ -101,13 +147,13 @@ ...@@ -101,13 +147,13 @@
<br> <br>
<br> <br>
<input type="radio" name="authtype" value="true" <input type="radio" name="authtype" value="basic"
id="http_basic_auth" <%=((httpBasicAuth) ? "checked" : "")%>> id="http_basic_auth" <%=("basic".equals(httpAuth) ? "checked" : "")%>>
<label for="http_basic_auth">HTTP basic auth - REST API <label for="http_basic_auth">HTTP basic auth - REST API
authentication with Openfire admin account.</label> authentication with Openfire admin account.</label>
<br> <br>
<input type="radio" name="authtype" value="false" <input type="radio" name="authtype" value="secret"
id="secretKeyAuth" <%=((!httpBasicAuth) ? "checked" : "")%>> id="secretKeyAuth" <%=("secret".equals(httpAuth) ? "checked" : "")%>>
<label for="secretKeyAuth">Secret key auth - REST API <label for="secretKeyAuth">Secret key auth - REST API
authentication over specified secret key.</label> authentication over specified secret key.</label>
<br> <br>
...@@ -116,6 +162,17 @@ ...@@ -116,6 +162,17 @@
<input type="text" name="secret" value="<%=secret%>" <input type="text" name="secret" value="<%=secret%>"
id="text_secret"> id="text_secret">
<br> <br>
<input type="radio" name="authtype" value="custom"
id="customFilterAuth" <%=("custom".equals(httpAuth) ? "checked" : "")%>>
<label for="secretKeyAuth">Custom authentication filter classname - REST API
authentication delegates to a custom filter implemented in some other plugin.
</label>
<div style="margin-left: 20px; margin-top: 5px;"><strong>Note: changing back and forth from custom authentication filter forces the REST API plugin reloading</strong></div>
<label style="padding-left: 25px" for="text_secret">Filter
classname:</label>
<input type="text" name="customAuthFilterClassName" value="<%= customAuthFilterClassName %>"
id="custom_auth_filter_class_name" style="width:70%;padding:4px;">
<br>
<br> <br>
<label for="allowedIPs">Allowed IP Addresses:</label> <label for="allowedIPs">Allowed IP Addresses:</label>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment