ForgeOpenPlatform
en

OpenPlatform

How an application connects to OpenPlatform: the launch and the verification

OpenPlatform · openplatform@5 openplatformprotocoltokensverifysso

When a user opens an application, OpenPlatform does not send a password or a cookie to it. It sends a one-time launch address, and the application calls back to OpenPlatform to learn who the user is. This page follows the code (schemas/account.js, action Account/run, and controllers/verify.js).

1. The launch

When the user clicks an application, the portal calls the API run/{appid}. OpenPlatform:

  1. checks that the application is in the list of the user (App not found otherwise) and that it is not disabled;
  2. creates a session of the application (table tbl_app_session) that expires after the setting app_session_expire (one day by default);
  3. builds the verification address: the platform url + /verify/?token= + the identifier of the session joined to the identifier of the installation with X, followed by X and a checksum (FUNC.checksum, which uses the secret saltchecksum);
  4. derives the two tokens of that session from the shared secrets of the application:
    • reqtoken = the MD5 of the verification address salted with the reqtoken of the application, in lower case;
    • restoken = the MD5 of that reqtoken salted with the restoken of the application;
  • opens the application at its url with one extra query parameter: openplatform=<verification address>~<reqtoken>.
  • For an application marked as a bookmark there is no handshake: the address gets ssid=<session checksum> instead.

    2. The verification

    The application takes the value of openplatform, which is the verification address, a ~ and the reqtoken of the session, and:

    1. computes its own restoken: the MD5 of the reqtoken salted with the restoken that it shares with OpenPlatform;
    2. calls GET on the whole value of openplatform (the ~ and the reqtoken stay in the query string) with the header x-token set to that restoken.

    OpenPlatform then (controllers/verify.js):

    1. splits the query token at the last ~ (the part after it is the reqtoken that it sent) and refuses the call when the header or the token is missing;
    2. checks the checksum of the session identifier, reads the session and compares both secrets (reqtoken and the restoken of the header); any difference is Invalid token;
    3. if the application has a list of allowed addresses, checks the address of the caller (Not allowed IP address);
    4. reads the user and refuses a disabled user (User has been disabled) or an inactive one (User is inactive);
    5. makes sure the user has the notification links of this application (table tbl_user_app);
    6. builds the answer and passes it through the transformation verify of the platform, so a deployment can add fields.

    The answer is a JSON object. Empty values are dropped from it. Its main fields are:

    FieldWhat it is
    id, name, email, photo, gender, referencewho the user is (photo is an absolute address)
    language, color, interface, darkmode, soundsthe preferences (the platform language and colour when the user has none)
    sathe user is an administrator of the platform
    permissionsthe value strings of the permissions of the user in this application
    groupsthe ids of the groups of the user
    appid, ssidthe application and the checksum of its session
    openplatformid, openplatformthe identifier and the address of the installation
    iframetrue unless the application is external
    notifythe address to send notifications to, when the user accepts them (notifications)
    platformthe name and logo of the platform, its groups and the applications of the user

    The answer is kept in an in-memory cache keyed by the session token (the part before the ~) and the cache is cleared every two minutes. A call with a token that is in that cache is answered from it, before the secrets are compared again, so a repeated verification inside that time is cheap.

    3. Asking again later

    GET /session/ takes the ssid that the application received (it also accepts openplatformid, token and session as the name of the parameter), checks its checksum and returns the user (id, language, name, color, sa, isonline) while the session of the user has not expired.

    What to remember when you build the application

    • Never ship the shared secrets to the browser: only the server of the application needs them.
    • Verify on the server and create your own session from the answer; the openplatform parameter is for one launch.
    • Use the permissions of the answer, not a role that the browser sends.
    • Total.js 5 has a native client for this family of protocols: see OPENCLIENT.