About this Manual

This manual is for Systems Administrators who administrating applications on Callimachus.

Callimachus is a highly scalable platform for creating and running data-driven websites. 3 Round Stones offers commercial support and private virtual cloud hosting for enterprises running Callimachus.

If you have not installed Callimachus yet, please follow the installation instructions in Getting Started with Callimachus.

Chapter 1. Callimachus Account Management

This describes Callimachus user accounts and their configuration options.

1.1. User Account

Accessing and configuring your user account is very simple, but depends heavily on what type of authentication was used to create your account. If you elected to login via an external service such as Google, Facebook, or Yahoo! then you have not created a new account on that Callimachus instance. In that case, any configuration should take place wherever the account is hosted.

However, if you have signed in via Digest Authentication (by creating a local Callimachus account) then you have a set of configuration options available to you within the Callimachus environment. You also have a dedicated account page from which you can alter these configurations. 

1.1.1. Access

To access your Callimachus User Account click on the Main Menu in the upper right of your Callimachus instance. At the bottom of the menu, just above "Sign out" will be a menu option pointing to your user account. The label will display however you signed in - via email: joe@example.com or via username: joe.

The resulting behavior however will differ based on authentication type.

Digest Authentication:

Clicking the profile link will take you to your dedicated Callimachus User Account. This page contains such information as full name, username and groups you belong to on the system. 

Non-Digest Authentication:

Clicking the profile link will do one of two things:

  • Take you to your account page on the external site with which you authenticated
  • Download the account file used for authentication on the external site

This behavior depends on how the external site is configured. For example, Facebook will take you to your Facebook profile page while Google will download the profile file associated with your account.

1.1.2. Configuration

Digest Authentication:

Configuration of digest accounts is accomplished via both the "View" and the "Edit" tab of the profile page. From the "View" tab you can click the Main Menu in the upper right of your Callimachus instance and select "Change password or email" to change the email associated with your account as well as the password used to access it.

From the "Edit" tab you can directly edit:

  • Full name
  • Additional information

Your username cannot be changed once the account has been created. If you want to change your username a new account will need to be created.

Non-Digest Authentication:

All configuration of non-digest authenticated accounts must take place on the external site. 

1.2. Account Invitations

1.2.1. Description

Account invitations are exactly what they sound like. They are the mechanism by which you can invite someone to create an account on your Callimachus instance. To invite a user navigate to the group to which you want them to belong (groups are found in /auth/groups/), select the "Edit" tab, and click the icon next to "Members". This will pop-up a dialog box for you to fill out with relevant information about the new user.

When a user is invited they will be able to create an account with whatever authentication options you have made available on your instance. 

A user MUST accept an invitation (follow the link in the email sent) before they are granted any permissions by the group.

1.2.2. Resend Invitations

Sometimes people forget to check their email or an invitation is filed into the spam folder and lost forever. That's why Callimachus offers the ability to resend an existing invitation. Rather than having to delete the old account and create a new one, you can just resend an invitation to the person reminding them to create an account. To do this, navigate to the user's account page in /auth/invited-users/ and click the Main Menu in the upper right and select "Re-send invitation". 

At any time you can check the /auth/invited-users/ directory to see which users have been invited but have not yet created an account. This is an easy way to keep track of potential and actual users of your Callimachus instance. 

1.2.3. Revoke Invitations

Invitations can be also be revoked, as well as resent. To revoke an invitation, navigate to the invited user's account page in /auth/invited-users/ and click the "Edit" tab. At the bottom of the edit tab you can click the red "Revoke invitation" button which will invalidate the pending invitation. 

1.3. Permissions

1.3.1. Description

Callimachus Permissions is how administrators have the ability to control who sees what in a given Callimachus instance. Different levels of access can be defined on a per-group basis depending on how public or private you want your Callimachus instance to be.

1.3.2. Access

Permissions can be set on a per-resource basis by accessing the main menu and selecting "Permissions" when viewing any Callimachus resource.

1.3.3. Usage

Callimachus Permissions offers five levels of increasing access:

  • Reader
    • Readers can view a read-only copy of the resource
  • Subscriber
    • Subscribers can view, see the history, and discuss the resource
  • Contributor
    • Contributors can create new resources in that defined space and edit the newly created resources
  • Editor
    • Editors can make changes using the edit tab and create new resources in that defined space
  • Administrator
    • Administrators can view, create and modify using any available operation

Under each of these permission levels different user groups can be assigned. For example, take a look at the default permission settings for the home folder (/?view). 

The following statements can be asserted from permissions edit tab:

  • The Public and System user groups have been given permission to view the Home Folder
  • The Everyone user group has been given permission to view the Home Folder, its history, and make comments on the resource discussion tab
  • The Users user group has been given permission to create and edit new resources in the Home Folder
  • The Power and Staff user groups have been given permission to create and edit new and existing resources in the Home Folder
  • The Admin user group has been given permission to perform any available operation on the Home Folder.

New user groups can be created and assigned custom permissions in this fashion.


Chapter 2. Callimachus Authentication

Callimachus allows for multiple authentication configurations including Facebook, Google, and Yahoo!. These can be useful for account management or for making your applications easily available to the public.

All forms of authentication are managed via the Authentication Manager which can be found under the "Edit" tab of the home folder. From here you can add, remove, and modify different forms of authentication for your Callimachus instance.

2.1. Digest Password Authentication

Digest password is the local authentication mechanism in Callimachus. It uses HTTP Digest Access Authentication, which never sends the user's password in cleartext. Unlike the other Cookie-based mechanisms available, which are vulnerable to session hijacking because they reuse the same token over and over, digest is based on a simple challenge-response paradigm, which passes a different token for every request and is the strongest mechanism provided for unencrypted HTTP requests.

The digest manager stores user names and a password digest in the configured User folder. Every password digest is salted with the configured Auth name. In some cases the Auth name may also be shown to user as part of a login prompt.

2.2. Facebook Authentication

Facebook authentication manager allows Callimachus Realms to authenticate user agents through an existing Facebook app. Any Facebook user is permitted to authenticate (provided they agree to share their email address). To configure Facebook authentication follow the following steps.

Step Action
1. Create a basic Facebook Application for authentication.
2. Obtain the Facebook App ID and Facebook App Secret for later use. These are displayed at the top of the Application page and can be reached by clicking the main menu dropdown on Facebook and selecting "Manage Apps". 
3. Configure your Facebook Application to communicate with your Callimachus instance. Under "Edit App", enter the URL of your Callimachus instance into the Site URL field of the "Website with Facebook Login" tab and hit "Save Changes".
4. Navigate to the Home Folder and click the "Edit" tab.
5. Click the icon next to "Authentication" to open the Authentication Manager and select "Faceboook authentication".
6. Provide a label, the Facebook App Id, the Facebook Secret, and a comment.
7. Save the form to complete the Facebook authentication setup

You should now be able to login to the instance using your Facebook account.

2.3. Google Authentication

The Google authentication mechanism allows any user agent (i.e. anybody) to authenticate using their Google account. Google distinguishes user identities by what realm they are logging into. Use the same OpenID realm pattern across different realms to have the realms share the same set of user identities. You will need to sent out an invitation to every user for every realm pattern to ensure users have correct access to every realm. Change the origin of the registration link in the invitation to match the invitation to the realm.

When filling out the New OpenID Manager dialog box, refer to the definitions below of the input boxes and their suggested values.

Term Definition Sample Value
Label Name for the authentication scheme. Google Accounts
OpenID Endpoint URL The URL against which the Google Accounts are authenticated. It is rare that this value will need to change. https://www.google.com/accounts/o8/ud
OpenID Realm Pattern A pattern that represents the part of URL-space for which an OpenID Authentication request is valid. http://*.example.com/
Comment Comment for the authentication scheme used for display at sign in. Sign in with your Google account
Authentication Button The image used for display purposes on the sign-in page.

An OpenID realm pattern is a pattern that represents the part of URL-space for which an OpenID Authentication request is valid. A realm pattern is designed to give the end user an indication of the scope of the authentication request. Google will present the authority portion of the realm pattern when requesting the end user's approval for an authentication request. The realm pattern is used by Google to allow the end user to automate approval of authentication requests for realms of this pattern.

A realm pattern is a URL, with the following changes:

  • A realm MUST NOT contain a URI fragment
  • A realm MAY contain a wild-card at the beginning of the URL authority section. A wild-card consists of the characters "*." prepended to the DNS name in the authority section of the URL.

2.4. Yahoo! Authentication

The Yahoo! authentication mechanism allows any user agent (i.e. anybody) to authenticate using their Yahoo! account. Yahoo! uses the same user identifier regardless of realm. The OpenID realm pattern is used to allow the end user to automate approval of authentication requests for realms of this pattern and the authority of the pattern is presented to the user.

The configuration process is identical to that of setting up Google Authentication, just with different values.

Term Definition Sample Value
Label Name for the authentication scheme. Yahoo! accounts
OpenID Endpoint URL The URL against which the Yahoo! Accounts are authenticated. It is rare that this value will need to change. https://open.login.yahooapis.com/openid/op/auth
OpenID Realm Pattern A pattern that represents the part of URL-space for which an OpenID Authentication request is valid. http://*.example.com/
Comment Comment for the authentication scheme used for display at sign in. Sign in with your Yahoo! account
Authentication Button The image used for display purposes on the sign-in page.

A realm pattern is a URL, with the following changes:

  • A realm MUST NOT contain a URI fragment
  • A realm MAY contain a wild-card at the beginning of the URL authority section. A wild-card consists of the characters "*." prepended to the DNS name in the authority section of the URL.

2.5. Other OpenID Provider Authentication

The OpenID provider authentication mechanism allows an user agent to authenticate using an external provider, such as a J2EE Servlet.

Term Definition Sample Value
Label Name for the authentication scheme. Other accounts
OpenID Endpoint URL The URL of the endpoint or servlet. http://example.com/servlets/servlet/AuthServlet
OpenID Realm Pattern A pattern that is passed to the endpoint as openid.realm query parameter. http://*.example.com/
Comment Comment for the authentication scheme used for display at sign in. Sign in with another account
Authentication Button The image used for display purposes on the sign-in page.

2.6. Custom J2EE Authorization

An external endpoint must support three modes for HTTP GET requests: checkid_setup, check_authentication, and checkid_immediate. The mode is indicated in the query string parameter "openid.mode".

2.6.1. Checkid Setup

The checkid_setup mode is called from the user agent Web browser. The endpoint should redirect the user to an login screen, if needed, and provide their name, email, and a unique identifier through redirecting the user to the return_to URL provided in the query string parameter "openid.return_to".


if ("checkid_setup".equals(request.getParameter("openid.mode"))) {
    // called by user agent to be redirected to login screen (as needed)
    String url = request.getRequestURL().toString();
    String return_to = request.getParameter("openid.return_to");
    StringBuilder sb = new StringBuilder("LoginServlet");
    sb.append("?return_to=").append(URLEncoder.encode(return_to));
    sb.append("&op_endpoint=").append(URLEncoder.encode(url));
    response.setStatus(303);
    response.setHeader("Location", sb.toString());
}

To have a J2EE application prompt the user agent to login, put a Servlet in a security-contraint. Shown here is LoginServlet protected by a realm in WEB-INF/web.xml.


<security-constraint>
  <display-name>Make sure all users have logged in before accessing the LoginServlet</display-name>
  <web-resource-collection>
     <web-resource-name>Protected Area</web-resource-name>
     <url-pattern>/servlets/servlet/LoginServlet</url-pattern>
  </web-resource-collection>
  <auth-constraint>
     <!-- Anyone with one of the listed roles may access this area -->
     <role-name>tomcat</role-name>
     <role-name>role1</role-name>
  </auth-constraint>
</security-constraint>

Once the user agent has authenticated/logged in, their name, email, and a persistent unique identifier must be sent to the return_to URL. The format of the response must conform to OpenID Authentication Response. The fullname and email must conform to OpenID Attribute Exchange Fetch Response Format.


// called by user agent to be redirected back after logging in
String return_to = request.getParameter("return_to");
String op_endpoint = request.getParameter("op_endpoint");
StringBuilder sb = new StringBuilder(return_to);
if (return_to.indexOf('?') > 0) {
    sb.append('&');
} else {
    sb.append('?');
}
sb.append("openid.ns=http://specs.openid.net/auth/2.0");
if (this.isAuthorized(request)) {
    String id = (String) request.getSession(true).getAttribute("id");
    if (id == null) {
        id = request.getSession(true).getId();
        request.getSession(true).setAttribute("id", id);
    }
    String user_fullname = this.getUserFullName(request);
    String user_email = this.getUserEmail(request);
    String user_uri = this.getUserIdentifier(request);
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    String now = df.format(new Date());
    sb.append("&openid.mode=id_res");
    sb.append("&openid.op_endpoint=").append(URLEncoder.encode(op_endpoint));
    sb.append("&openid.claimed_id=").append(URLEncoder.encode(user_uri));
    sb.append("&openid.identity=").append(URLEncoder.encode(user_uri));
    sb.append("&openid.return_to=").append(URLEncoder.encode(return_to));
    sb.append("&openid.ns.ax=http://openid.net/srv/ax/1.0");
    sb.append("&openid.ax.mode=fetch_response");
    sb.append("&openid.ax.type.email=http://axschema.org/contact/email");
    sb.append("&openid.ax.type.fullname=http://axschema.org/namePerson");
    sb.append("&openid.ax.value.email=").append(URLEncoder.encode(user_email));
    sb.append("&openid.ax.value.fullname=").append(URLEncoder.encode(user_fullname));
    sb.append("&openid.response_nonce=").append(now).append(URLEncoder.encode(id));
} else {
    sb.append("&openid.mode=cancel");
}
response.setStatus(303);
response.setHeader("Location", sb.toString());

In the above example the user agent session ID is encoded in the openid.response_nonce parameter that is sent to the return_to URL, this will later be used to verify the information is valid.

2.6.2. Check Authentication

Once the user agent has been authenticated, the system must verify the information directly to the external endpoint. In order for a Servlet endpoint to access the necessary HttpSession information, an HttpSessionListener can be used to track the local user agent sessions. A listener must be registered in WEB-INF/web.xml.


<listener>
    <listener-class>SessionTracker</listener-class>
</listener>

public class SessionTracker implements HttpSessionListener {
  public void sessionCreated(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    ServletContext ctx = session.getServletContext();
    Map<String, HttpSession> sessions = (Map) ctx.getAttribute("active-sessions");
    if (sessions == null) {
        synchronized (ctx) {
            sessions = (Map) ctx.getAttribute("active-sessions");
            if (sessions == null) {
                sessions = Collections.synchronizedMap(new HashMap<String, HttpSession>());
            }
            ctx.setAttribute("active-sessions", sessions);
        }
    }
    String id = (String) session.getAttribute("id");
    if (id == null) {
        id = session.getId();
        session.setAttribute("id", id);
    }
    sessions.put(id, session);
  }
  public void sessionDestroyed(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    ServletContext ctx = session.getServletContext();
    Map<String, HttpSession> sessions = (Map) ctx.getAttribute("active-sessions");
    if (sessions != null) {
        sessions.remove(session.getId());
    }
  }    
}

The system will sent a GET request to the external endpoint and pass all the parameters that it was sent for verification. The endpoint must verify that all of the parameters are correct and none of them have been modified in transit. The response must comply with Verifying Directly with the OpenID Provider.


if ("check_authentication".equals(request.getParameter("openid.mode"))) {
    // called by client for session validation
    String user_fullname = request.getParameter("openid.ax.value.fullname");
    String user_email = request.getParameter("openid.ax.value.email");
    String user_uri = request.getParameter("openid.identity");
    String response_nonce = request.getParameter("openid.response_nonce");
    String sessionId = response_nonce.substring(response_nonce.indexOf('Z') + 1);
    ServletContext ctx = request.getServletContext();
    Map<String, HttpSession> sessions = (Map) ctx.getAttribute("active-sessions");
    HttpSession session = sessions == null ? null : sessions.get(sessionId);

    response.setContentType("text/plain");
    PrintWriter out = response.getWriter();
    out.print("ns:http://specs.openid.net/auth/2.0\n");
    if (session != null
            && user_fullname.equals(this.getUserFullName(session))
            && user_email.equals(this.getUserEmail(session))
            && user_uri.equals(this.getUserIdentifier(session))) {
        out.print("is_valid:true\n");
    } else {
        out.print("is_valid:false\n");
    }
}

2.6.3. Checkid Immediate

If the validation fails the system will redirect their user agent to the endpoint with the mode checkid_immediate. This is similar to checkid_setup, but indicates the endpoint should redirect the user directly back to the system without any user prompts. If the user is not logged in, the response should contain the mode setup_needed to indicate the user must login before proceeding, otherwise a mode of id_res with updated credentials (as with checkid_setup) should be returned.


if ("checkid_immediate".equals(request.getParameter("openid.mode"))) {
    // called by user agent to be immediately redirected back
    String return_to = request.getParameter("openid.return_to");
    String op_endpoint = request.getRequestURL().toString();
    StringBuilder sb = new StringBuilder(return_to);
    if (return_to.indexOf('?') > 0) {
        sb.append('&');
    } else {
        sb.append('?');
    }
    sb.append("openid.ns=http://specs.openid.net/auth/2.0");
    if (this.isAuthorized(request)) {
        String id = request.getSession(true).getId();
        String user_fullname = this.getUserFullName(request);
        String user_email = this.getUserEmail(request);
        String user_uri = this.getUserIdentifier(request);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        String now = df.format(new Date());
        sb.append("&openid.mode=id_res");
        sb.append("&openid.op_endpoint=").append(URLEncoder.encode(op_endpoint));
        sb.append("&openid.claimed_id=").append(URLEncoder.encode(user_uri));
        sb.append("&openid.identity=").append(URLEncoder.encode(user_uri));
        sb.append("&openid.return_to=").append(URLEncoder.encode(return_to));
        sb.append("&openid.ns.ax=http://openid.net/srv/ax/1.0");
        sb.append("&openid.ax.mode=fetch_response");
        sb.append("&openid.ax.type.email=http://axschema.org/contact/email");
        sb.append("&openid.ax.type.fullname=http://axschema.org/namePerson");
        sb.append("&openid.ax.value.email=").append(URLEncoder.encode(user_email));
        sb.append("&openid.ax.value.fullname=").append(URLEncoder.encode(user_fullname));
        sb.append("&openid.response_nonce=").append(now).append(URLEncoder.encode(id));
    } else {
        sb.append("&openid.mode=setup_needed");
    }
    response.setStatus(303);
    response.setHeader("Location", sb.toString());
}

2.7. Credentials

2.7.1. Description

Credentials are the username and passwords that should be used for outgoing requests from scripts, queries, or pipelines within a given realm. For example in order to be able to take any action against most servers you need to authenticate yourself. You can do this by hardcoding your username and password into the query string but that is a clunky solution and a potential security risk. That is why Callimachus allows you to store credentials system-wide and whenever one of your scripts, queries, or pipelines is challenged for authentication Callimachus will check your credentials for the proper login information. 

2.7.2. Configuration

Create a Credential

To setup Credentials for your system navigate to the Home Folder and click the "Edit" tab. From here click the icon next to "Credentials" and fill in the form with the appropriate values.

Field Explanation Sample Value
Authority This is the host name of the service. Must be entered in format authority:port or authority if the port is 80. people.example.com
Username The username used to authenticate against the service specified in Authority. username
Password The password tied to the username used to authenticate against the service specified in Authority. password

After filling in the form, click Create and your credentials will be saved. Don't forget to hit "Save" on the Home Folder itself or the relationship will not be created.

Edit a Credential

If you typed the password for a given credential incorrectly you can find it in /auth/credentials. From there click the "Edit" tab and retype the password. If you wish to rename a Credential or change the Authority or Port you will need to delete that Credential and create a new one. 

Remove or Delete a Credential

Removing a Credential means that it no longer applys to your Callimachus instance. The Credential itself stil exists in /auth/credentials and can be reapplied at a later time if you desire. 

Deleting a Credential, on the other hand, removes the Credential entirely from the system along with any relationships to the system it may have. This cannot be undone and if you do so unintentionally you can recreate it via the Create menu. 

2.7.3. Usage

Now that credentials have been stored in your Callimachus instance, you can access that system without explicitly authenticating each and every time. For example, rather than having to write a query like this:


PREFIX foaf:   <http://xmlns.com/foaf/0.1/>

SELECT ?name WHERE {
  ?myself a foaf:Person
    ; ​foaf:knows ?person .
  
  SERVICE <http://username:password@people.example.com/sparql> { 
    ?person foaf:name ?name . 
  } 
}

which exposes in plain text both your username and password, you can write a query like this:


PREFIX foaf:   <http://xmlns.com/foaf/0.1/>

SELECT ?name WHERE {
  ?myself a foaf:Person
    ; ​foaf:knows ?person .
  
  SERVICE <http://people.example.com/sparql> { 
    ?person foaf:name ?name . 
  } 
}

that doesn't include that information. Callimachus takes care of the authentication behind the scenes.