Architecture > Authentication
Custom Entitlements
On initial launch, AMI runs using a set of default login properties (demo, demo123).
This is generally only recommended for demonstration purposes. For actual production cases, we recommend a combination of the encryption and custom entitlements plugins to assign the correct permissions to users.
Overview
Custom entitlements are given by implementing an instance of the AMI factory AmiAuthenticatorPlugin. The plugin should do the following:
There are two different entry points into AMI, each of which can have their own instance of an authentication adapter:
-
Frontend Web Interface:
- Used when using a browser to access AMI
- A user must supply a username and password via the html login page (see the properties)
-
Backend Command line interface:
- Used when accessing AMI's in-memory database via the command line interface
- A user must execute the
login command, which in turn calls an instance of this plugin (see the properties)
AMI Predefined Attributes
| Attribute |
Value |
Description |
ISADMIN |
true or false |
- If
true, the user will be logged into the website with admin rights
|
ISDEV |
true or false |
- If
true, the user will be logged into the website with developer rights
|
DEFAULT_LAYOUT |
supplied_layout.ami or ABSOLUTE:path/to/supplied_layout.ami |
- If set, this will be the default layout loaded from the cloud directory on login
- You may also specify other directories with the appropriate prefix flag of either:
ABSOLUTE, LOCAL, CLOUD, or SHARED
|
LAYOUTS |
layout1.ami,layout2.ami... or ABSOLUTE:path/to/...ami |
- A comma-delimited list of regular expressions for layouts that are available in cloud
- You may use other directories with the appropriate prefix flag either
ABSOLUTE, LOCAL, CLOUD, or SHARED
|
amiscript.variable.<some_varname> |
key-value pair, e.g region=New York |
- Supply a session variable of type
some_varname and value to add to the user session - For example:
amiscript.variable.region=New York
|
AMIDB_PERMISSIONS |
READ,WRITE,ALTER,EXECUTE |
- A comma-delimited combination of AMIDB permissions which controls permissions for the user when logging in via JDBC or DB command line
|
Deprecated
| Attribute |
Description |
amivar_<some_varname> |
- A variable named
user.some_varname of type string is added to the user's session - Use
amiscript.variable.<some_varname> instead
|
ami_layout_shared |
- If set, this will be the default layout loaded from the shared directory on login
- Use
DEFAULT_LAYOUT instead
|
Properties
| ami.auth.plugin.class=fully_qualified_class_name # for Web access
ami.db.auth.plugin.class=fully_qualified_class_name # for Center access
|
Example
This basic example will run through how to use the AMI Authenticator factory in Java to implement user permissions. Ensure that autocode.jar and out.jar are included in your project's classpath.
Setup
For custom entitlements, you will need to do the following:
- Create a custom entitlements plugin that implements the AMI package
com.f1.ami.web.auth.AmiAuthenticatorPlugin as Java class.
- Save and export the project as a
.jar file and add it to your AMI amione/lib folder as with any other custom plugin.
- Implement custom permission logic via the Custom Callbacks menu in AMI Web.
Java Code
| package authenticator_example;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import com.f1.ami.web.auth.AmiAuthAttribute;
import com.f1.ami.web.auth.AmiAuthResponse;
import com.f1.ami.web.auth.AmiAuthenticatorPlugin;
import com.f1.ami.web.auth.BasicAmiAttribute;
import com.f1.ami.web.auth.BasicAmiAuthResponse;
import com.f1.ami.web.auth.BasicAmiAuthUser;
import com.f1.container.ContainerTools;
import com.f1.utils.PropertyController;
public class TestAuth implements AmiAuthenticatorPlugin {
@Override
public void init(ContainerTools tools, PropertyController props) {
// TODO Auto-generated method stub
}
@Override
public String getPluginId() {
return "TestAuthenticator";
}
@Override
public AmiAuthResponse authenticate(String namespace, String location, String user, String password) {
final Map<String, Object> attributes = new HashMap<>();
attributes.put("ISDEV","false"); // Set to true for developer privileges
attributes.put("ISADMIN", "false"); // Set to true for admin privileges
attributes.put("DEFAULT_LAYOUT", "default.ami"); // Layout loaded on startup from cloud
attributes.put("LAYOUTS", "layout1.ami,layout2.ami"); // Supply as many layouts from cloud as needed
attributes.put("amiscript.variable.region", "New York"); // Creates a custom variable in the user session assigning "New York" to the user's "region"
Map<String, Object> allowedWindows = new HashMap<String, Object>();
allowedWindows.put("namespace1", new HashSet(Arrays.asList("Window1PNL", "Window2PNL")));
attributes.put("amiscript.variable.allowedWindows", allowedWindows); // This adds a custom AMI Session Variable called `allowedWindows` which will then be used in some custom script to control which windows are visible
attributes.put("amiscript.variable.env", "UAT"); // This adds a custom AMI Session Variable called `env` to "UAT"
// Use AmiAuthResponse.STATUS_GENERAL_ERROR if authentication failed.
return new BasicAmiAuthResponse(AmiAuthResponse.STATUS_OKAY, null, new BasicAmiAuthUser(user, attributes));
}
}
|
In Web
Ensure you have first added to local.properties the fully qualified class name of the plugin, in this case:
| ami.auth.plugin.class=authenticator_example.TestAuth
|
Controlling which windows are visible can then be done using the onStartup() Callback:
Note
The following is required: Dashboard Settings->User Preferences Namespace
| // First, let's find out which dashboard the user has loaded.
String layoutNamespace = session.getUserPreferencesNamespace();
// Get set of Allowed Windows for the current dashboard, per entitlements.
//Note, the allowedWindows map was defined and populated in the entitlements plugin above
Set allowedWindowsSet = allowedWindows.get(layoutNamespace);
// Loop through all windows in the dashboard, marking any windows that are not in the entitlements as HIDDEN so the user does not have access to them
Map windowsMap = session.getWindowsMap();
for(String id: windowsMap.getKeys()){
if(allowedWindowsSet == null || !allowedWindowsSet.contains(id)){
Window w = windowsMap.get(id);
w.setType("HIDDEN");
w.minimize();
}
}
|
Note
These are the same instructions that can be found in the user permissions section on this page.
Blank AmiAuthenticatorPlugin Java File
| import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import com.f1.ami.web.auth.AmiAuthAttribute;
import com.f1.ami.web.auth.AmiAuthResponse;
import com.f1.ami.web.auth.AmiAuthenticatorPlugin;
import com.f1.ami.web.auth.BasicAmiAttribute;
import com.f1.ami.web.auth.BasicAmiAuthResponse;
import com.f1.ami.web.auth.BasicAmiAuthUser;
import com.f1.container.ContainerTools;
import com.f1.utils.PropertyController;
/**
*
* A single instance will be loaded at startup of the web server and used for authenticating users for login verification.
*
*/
public interface AmiAuthenticatorPlugin extends AmiPlugin {
public static final String NAMESPACE_AMIADMIN_CLI = "AMIADMIN_CLI";
public static final String NAMESPACE_AMIDB_JDBC = "AMIDB_JDBC";
public static final String NAMESPACE_AMIDB_CLI = "AMIDB_CLI";
public static final String NAMESPACE_AMIWEB_GUI = "AMIWEB_GUI";
/**
* will be called right after object construction with its properties.
*
* @param tools
* has various tools that can be used for accessing system-wide items such as properties, clock, thread pool, object pool, etc
* @param props
* properties specific to this plugin
*/
public void init(ContainerTools tools, PropertyController props);
/**
* A unique identifier, within the scope of the class type of the plugin. Note, this must not change for the life of the instance of the plugin.
*/
public String getPluginId();
/**
*
* @param namespace
* this is the value specified using the f1.appname property and is useful when there are multiple web servers that should have distinct login permissions.
* @param location
* the ip address of the remote user (as gathered by using the http connection's remote ip)
* @param user
* name passed into the user field on the login page
* @param password
* password passed into the user field on the login page
* @return The result of doing the authentication, should never be null
*/
public AmiAuthResponse authenticate(String namespace, String location, String user, String password);
}
|