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 {
}
// HTTP Basic Auth or Shared Secret key
if (plugin.isHttpBasicAuth()) {
if ("basic".equals(plugin.getHttpAuth())) {
String[] usernameAndPassword = BasicAuth.decode(auth);
// If username or password fail
......
......@@ -39,6 +39,8 @@ import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import org.jivesoftware.util.StringUtils;
import org.jivesoftware.openfire.plugin.rest.service.JerseyWrapper;
/**
* The Class RESTServicePlugin.
*/
......@@ -47,6 +49,8 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
/** The Constant INSTANCE. */
public static final RESTServicePlugin INSTANCE = new RESTServicePlugin();
private static final String CUSTOM_AUTH_FILTER_PROPERTY_NAME = "plugin.restapi.customAuthFilter";
/** The secret. */
private String secret;
......@@ -56,8 +60,12 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
/** The enabled. */
private boolean enabled;
/** The http basic auth. */
private boolean httpBasicAuth;
/** The http auth. */
private String httpAuth;
/** The custom authentication filter */
private String customAuthFilterClassName;
/**
* Gets the single instance of RESTServicePlugin.
......@@ -78,12 +86,15 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
secret = StringUtils.randomString(16);
setSecret(secret);
}
// See if Custom authentication filter has been defined
customAuthFilterClassName = JiveGlobals.getProperty("plugin.restapi.customAuthFilter", "");
// See if the service is enabled or not.
enabled = JiveGlobals.getBooleanProperty("plugin.restapi.enabled", false);
// 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
// means that this filter is disabled.
......@@ -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.
*
......@@ -201,6 +229,26 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
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.
*
......@@ -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() {
return httpBasicAuth;
public String getHttpAuth() {
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) {
this.httpBasicAuth = httpBasicAuth;
JiveGlobals.setProperty("plugin.restapi.httpAuth.enabled", httpBasicAuth ? "true" : "false");
public void setHttpAuth(String httpAuth) {
this.httpAuth = httpAuth;
JiveGlobals.setProperty("plugin.restapi.httpAuth", httpAuth);
}
/* (non-Javadoc)
......@@ -271,8 +319,10 @@ public class RESTServicePlugin implements Plugin, PropertyEventListener {
this.enabled = Boolean.parseBoolean((String) params.get("value"));
} else if (property.equals("plugin.restapi.allowedIPs")) {
this.allowedIPs = StringUtils.stringToCollection((String) params.get("value"));
} else if (property.equals("plugin.restapi.httpAuth.enabled")) {
this.httpBasicAuth = Boolean.parseBoolean((String) params.get("value"));
} else if (property.equals("plugin.restapi.httpAuth")) {
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 {
this.enabled = false;
} else if (property.equals("plugin.restapi.allowedIPs")) {
this.allowedIPs = Collections.emptyList();
} else if (property.equals("plugin.restapi.httpAuth.enabled")) {
this.httpBasicAuth = false;
} else if (property.equals("plugin.restapi.httpAuth")) {
this.httpAuth = "basic";
} else if(property.equals(CUSTOM_AUTH_FILTER_PROPERTY_NAME)) {
this.customAuthFilterClassName = null;
}
}
......
<%@ page
import="java.util.*,
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.util.*,org.jivesoftware.openfire.plugin.rest.RESTServicePlugin"
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.util.*,org.jivesoftware.openfire.plugin.rest.RESTServicePlugin,
org.jivesoftware.openfire.container.Plugin,
org.jivesoftware.openfire.container.PluginManager"
errorPage="error.jsp"%>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
......@@ -20,20 +22,45 @@
boolean success = request.getParameter("success") != null;
String secret = ParamUtils.getParameter(request, "secret");
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 customAuthFilterClassName = ParamUtils.getParameter(request, "customAuthFilterClassName");
String loadingStatus = null;
final PluginManager pluginManager = admin.getXMPPServer().getPluginManager();
RESTServicePlugin plugin = (RESTServicePlugin) XMPPServer.getInstance().getPluginManager()
.getPlugin("restapi");
// Handle a save
Map errors = new HashMap();
if (save) {
if("custom".equals(httpAuth)) {
loadingStatus = plugin.loadAuthenticationFilter(customAuthFilterClassName);
}
if (loadingStatus != null) {
errors.put("loadingStatus", loadingStatus);
}
if (errors.size() == 0) {
boolean is2Reload = "custom".equals(httpAuth) || "custom".equals(plugin.getHttpAuth());
plugin.setEnabled(enabled);
plugin.setSecret(secret);
plugin.setHttpBasicAuth(httpBasicAuth);
plugin.setHttpAuth(httpAuth);
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");
return;
}
......@@ -41,8 +68,9 @@
secret = plugin.getSecret();
enabled = plugin.isEnabled();
httpBasicAuth = plugin.isHttpBasicAuth();
httpAuth = plugin.getHttpAuth();
allowedIPs = StringUtils.collectionToString(plugin.getAllowedIPs());
customAuthFilterClassName = plugin.getCustomAuthFilterClassName();
%>
<html>
......@@ -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">
<fieldset>
......@@ -101,13 +147,13 @@
<br>
<br>
<input type="radio" name="authtype" value="true"
id="http_basic_auth" <%=((httpBasicAuth) ? "checked" : "")%>>
<input type="radio" name="authtype" value="basic"
id="http_basic_auth" <%=("basic".equals(httpAuth) ? "checked" : "")%>>
<label for="http_basic_auth">HTTP basic auth - REST API
authentication with Openfire admin account.</label>
<br>
<input type="radio" name="authtype" value="false"
id="secretKeyAuth" <%=((!httpBasicAuth) ? "checked" : "")%>>
<input type="radio" name="authtype" value="secret"
id="secretKeyAuth" <%=("secret".equals(httpAuth) ? "checked" : "")%>>
<label for="secretKeyAuth">Secret key auth - REST API
authentication over specified secret key.</label>
<br>
......@@ -116,6 +162,17 @@
<input type="text" name="secret" value="<%=secret%>"
id="text_secret">
<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>
<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