• Interacting with OpenCore

last modified January 24, 2008 by cdwinslow

This API may be modified or expanded at any point to meet the needs of opencore's users. In the short term, the most likely changes are exposing additional information at these URIs and switching the data format. (I don't see the point of the arbitrary XML tags we're using)

Opencore API

opencore exposes an API for reading data about specific projects, teams and users. There is currently no API for modifying data within opencore, nor is there any API for listing projects, teams or users; to get information about an object its id must already be known.

Resource Location Protection
Project information
/siteroot/projects/{project-id}/info.xml No authentication required
Team information
/siteroot/projects/{project-id}/memberships.xml Identical to project security
Member information
Must be {user-id} or site admin

/siteroot/people/all.xml Must be site admin


To fetch information about a project:
GET /siteroot/projects/{project-id}/info.xml
This will return an XML document which describes the project's security policy in the following format:
where `{current_policy}` is a string: "closed_policy", "medium_policy" or "open_policy".

To fetch information about a project's team:
GET /siteroot/projects/{project-id}/memberships.xml
This will return an XML document which describes the project's team, with a `member` entry for each active member in the project, in the following format.
`{user-id}` is a string: the user's id (username). `{membership-role}` is a string expressing the user's highest role in the project: "ProjectAdmin" or "ProjectMember". Note that this implies that membership roles are strictly hierarchical; external applications should grant all permissions associated with ProjectMembers to ProjectAdmins as well.

Note that only active project members are described here. There is currently no way to get a list of pending members (users who have requested to join a project and have not yet been confirmed by a project admin, and users who have been invited to join a project and have not yet accepted the invitation) or inactive members (former project members who have left or been removed from the project). I have no idea whether private memberships are exposed here. I should find out immediately.

Projects: Security

Currently the above resources do not respect the security of the project that they describe and whose URI they are under. Actually, this is not true, because of placeful workflow magic. The practical results are as follows.

The `info.xml` resource is entirely unprotected and can be fetched without any authentication. This is bad (though not terrible, since the only thing it exposes is the project's security policy, and it's easy to determine that a project exists and has a closed policy in many ways on our site) and will be changed shortly.

The `members.xml` resource is protected: for a project whose security policy is either open_policy or medium_policy, this resource can be fetched without any authentication. For a project with a closed_policy security policy, the resource can only be fetched by an authenticated user with proper authorization: an active member of the team, or a site administrator. The simplest way to provide this authentication is to encode the username and password inline into the URI of the request (e.g. `GET http://myusername:mypassword@localhost/openplans/projects/myproject/members.xml`) but this cannot possibly be at all secure. (Esepcially since our site seems to behave slightly weirdly with https)


To fetch information about a user:
GET /siteroot/people/{user-id}/info.xml
This will return an XML document with personal information about the user, in the following format:
`{user-fullname}` is a string: the user's full name. Users are not required to fill out their full name at any point, so this may be blank.

To fetch information about all users:
GET /siteroot/people/all.xml
This will return an XML document with personal information about all users. Only site administrators can access this resource.

Users: Security

Since I expect that the user info resource will soon provide additional data which we do not expose publically, such as the user's email address, access to this resource for a particular user is strictly limited to requests that are authenticated as that user himself and to site administrators.

Authenticating Users With Opencore

When a user successfully logs in with opencore, opencore sets a cookie called '__ac'. External applications can use this cookie to get and verify the identity of the requesting user. In order to verify the cookie, all external applications needs to share an unguessable secret with opencore; the cookie is generated using this secret. (The secret lives in a file on disk; look for zope/secret.txt, /var/lib/secret.txt, or ask Jeff.)

This is how tasktracker identifies the user and verifies the cookie. There's a start toward a plain-english explanation of what this does on the Geoserver wiki at http://docs.codehaus.org/display/GEOSDOC/OpenPlans+Authentication.
            cookie = BaseCookie(environ['HTTP_COOKIE'])
            morsel = cookie['__ac']
        except KeyError:
            return False

            username, auth = base64.decodestring(unquote(morsel.value)).split("\0")
        except ValueError:
            raise BadCookieError

        if not auth == hmac.new(self.secret, username, sha).hexdigest():
            return False

Once the cookie has been validated and the username has been extracted from the cookie, the external application can request additional required information about the user via the opencore API described above.


Logging In Opencore Users

As an alternative to having opencore log in the user and set a cookie, you can fetch the cookie hash for any user and set the cookie manually:

POST /openplans/people/{user-id}/get-hash
parameters: __ac_password (the user's password)

Provided the password is correct, this will return:


It's also worth mentioning that

External applications can get "context information" (at the moment it's actually just project information if you happen to be in a project context) about the request by looking for the HTTP_X_OPENPLANS_PROJECT header in the request. VHoster automatically sets this header to {project-id} all incoming requests if the URI of the request looks like /siteroot/projects/{project-id}. Note that if you are making an internal request between applications which bypasses VHoster you may need to set this header directly if the receiving application expects the header to be present.