Account Manager

The Account Manager service (com.palm.service.accounts) provides central account and credentials management on the device. Synergy services are services on the webOS message bus that provide a connection to an outside data source (i.e., for log in and syncing) and manage the caching of credentials and configuration data on the device. To interact with the Accounts service, Synergy services need to register an Account template file (read at Account service start-up) that contains callbacks and metadata. Synergy applications can use the Account service when interacting with external account providers such as Facebook, Google, Yahoo, and LinkedIn. Third-party applications can use the service to interface with their own providers and integrate with the Palm Accounts app which provides a unified and standard Account UI.

Providers give users capabilities such as contacts, calendar, blogging, email, and so on. For a single user, each of these capabilities can have its own provider account. In addition, each capability can have its own protocol implementation, such as Gdata, Exchange, POP, IMAP, and so on.

webOS supports a number of built-in providers and their capabilities which HP or 3rd parties may extend in the future. Providers determine the types of accounts and credentials that exist on the device which can vary by capability. Account objects stored on the device (proxies for real provider accounts) are a combination of credentials for a particular provider, with one or more capabilities enabled. For a given provider and user, only one Account object can exist in the db8 database. Using the Account service methods, apps and services can list account information, create new accounts, and alter existing accounts.

In this section

To integrate with the Account Manager service, applications need to create, configure or incorporate the following:

  • Design Points - Things to keep in mind when you are developing your Account and Synergy services.

  • Account Manager Service Interface (APIs) - The Accounts service (com.palm.service.accounts) allows users to list, create, and alter localized accounts. Note that this applies to Account objects in the db8 database on the device, not creating or deleting an actual provider (Facebook, Google, etc.) account. The user must already have a provider account.

    Once one capability is enabled, the Account service can enable all provider capabilities for the user. For example: if the user has Google accounts for contacts, messaging, mail, and calendar, the Accounts service can enable all of them.

    This service also handles the reading and writing of account credentials and other sensitive data. See the Account Manager API for more information.

  • Synergy Service - Your app needs to provide a Synergy service on the bus that implements a connection with an outside data source. This service can also implement methods the Account Manager calls when an account is created or altered.

  • Account Template - Your Synergy service needs to register an Account template file containing callbacks and metadata with the Accounts service. The Accounts service invokes these callbacks to validate credentials and notify the service about account creation or modification. This file is read and registered each time the Accounts service starts up.

    For third parties installing a service in a packaged file, your template file must be named account_template.json. See the Template data type for more information about this file's configuration.

  • Accounts UI library - Your JavaScript app should include the Accounts UI library (accounts.ui) to handle common UI tasks such as launch screens, account preferences, and account listings. This library provides the baseline functionality for the standalone Accounts app.

  • Custom Validator - This is optional. Most account templates can utilize the standard username/password Accounts UI when logging in. If not, the Accounts Framework allows template authors to specify a custom UI to display in lieu of the standard login UI.

See also:

 


Design points

  • The Accounts preferences app and all PIM (Personal Information Manager) apps share an Accounts UI component. PIM apps need only implement their app-specific preferences UI (e.g. calendar color).

  • The Accounts UI will talk to the Accounts service (com.palm.service.accounts) to coordinate account creation, modification, and removal.

  • The Accounts Service triggers various procedures for account actions, including:

    • On account creation, begins initial syncs.
    • On capability removal, deletes PIM data.
    • On username/password change, calls all validators to generate custom authorization tokens.
  • The Accounts Service acts as a proxy for credentials read/write access for white-listed services. For example: the IMAP service asks the account service for the gmail authorization token when doing a gmail sync.

 


Account Manager Service Interface (APIs)

Developer options for accessing the Account Manager:

Methods

  • createAccount — Create an account object in the db8 database.

  • deleteAccount — Delete an account object in the db8 database.

  • getAccountInfo — Retrieve a specific account object from the db8 database.

  • modifyAccount — Modify an account object in the db8 database.

 


createAccount

Creates an Account object in the db8 database that serves as a proxy for a real provider (i.e., Facebook, Google) account. The caller can specify the provider capabilities (email, calendar, etc.) they want to enable for the account. Callers can pass configuration data and credentials for one or more provider accounts. An account can have multiple named credentials objects. For example, it could have objects named "common", "smtp", and "imap". With these, the SMTP and IMAP services could keep their own authorization tokens, and all other Synergy services could use the "common" credentials. Typically, credential and configuration information is returned from a validate user login API. Configuration information is passed to the Synergy service's onCreate method and credentials are kept in encrypted storage.

This method does the initial writing of account credentials to encrypted storage; after this, you can use the writeCredentials method to alter them.

To avoid duplicates, usernames should be "normalized," that is, incomplete usernames (i.e., "johndoe") should be turned into fully-qualified, unambigous usernames (i.e., "johndoe@gmail.com").

Syntax

{
    "templateId"   : string,
    "capabilityProviders": [ {
    "id"         : string,
    "capability" : string
    }],
    "username"     : string,
    "alias"        : string,
    "credentials"  : {
        <any string> : CredentialsObj object,
        ...
    },
    "config"       : any,
    "sync"         : boolean
}

Parameters

Argument Required Type Description
templateId Yes string ID of the template file (i.e., "com.palm.google") stored in /usr/palm/public/accounts/ for the account's Synergy service. See the Template data type for more information.
capabilityProviders No array of inline objects See two elements below.
id No string Capability ID in template, i.e., "com.palm.gdata.calendar"
capability No string Capability name, i.e., "CONTACTS"
username Yes string User name.
alias No string Alias name. Account name in UI.
credentials Yes CredentialsObj object(s) One or more named credential objects. See example.
config Yes any Opaque config objects passed to Synergy service.
sync No boolean Automatic backup flag. Default is true.

Returns

{
    "returnValue" : boolean,
    "errorCode"   : string,
    "errorText"   : string,
    "result"      : Account 
}
Argument Required Type Description
returnValue Yes boolean true (success) or false (failure).
errorCode No string Returned on failure.
errorText No string Returned on failure. Text describing error.
result Yes Account Created Account object.

Example with multiple credential objects

this.controller.serviceRequest("palm://com.palm.service.accounts/", {
    method: "createAccount",
    parameters: {
        "templateId"          : "com.palm.sample",
        "capabilityProviders" : [{"id":"com.palm.sample.contacts", "capability":"CONTACTS"}],
        "username"            : "Souffle",
        "alias"               : "puffy",
        "credentials"         : {
            "common":{ "password" : "laddw99", "authToken":"8ukkk9##99"}, 
            "smtp":{ "password" : "lawyer99", "authToken":"8u0009##99"}
        },
        "config"              : {  "ip":"12.225.172.8" }
    },
    onSuccess: function(r) { Mojo.Log.info("Account object = "+JSON.stringify(r)); },
    onFailure: function(r) { Mojo.Log.info("createAccount failure, err="+JSON.stringify(r)); }      
});

 


deleteAccount

Given an account ID, deletes an account object in db8. The account's Synergy service is notified through its onDelete and onEnabled (with "enabled = false") methods. The Synergy should use the onEnabled method to clean up all sync data associated with the account.

Syntax

{
    "accountID"  : string
}

Parameter

Argument Required Type Description
accountId Yes string db8 Account ID

Returns

{
    "returnValue" : boolean,
    "errorCode"   : string,
    "errorText"   : string      
}
Argument Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Returned on failure.
errorText No string Returned on failure. Text describing error.

Example

this.controller.serviceRequest("palm://com.palm.service.accounts/", {
    method: "deleteAccount",
    parameters: {
                "accountId": "2+PO"
    },
    onSuccess: function(){ Mojo.Log.info("deleteAccount success"); },
    onFailure: function(e) { 
        Mojo.Log.info("deleteAccount failure, err="+JSON.stringify(r));
    }                
});

 


getAccountInfo

Given an account ID, returns a db8 Account object combined with a Template object.

Syntax

{
    "accountId" : string
}

Parameters

Argument Required Type Description
accountId Yes string db8 account ID.

Returns

{
    "returnValue" : boolean,
    "errorCode"   : string,
    "errorText"   : string, 
    "result"      : Combined Account and Template object
}
Argument Required Type Description
returnValue Yes boolean true (success) or false (failure).
errorCode No string Returned on failure.
errorText No string Returned on failure. Text describing error.
result No Combined Account and Template object Account object combined with Template object.

Example

this.controller.serviceRequest("palm://com.palm.service.accounts/", {
    method: "getAccountInfo",
    parameters: {
        "accountId": "2+31",
    },
    onSuccess: function(r) { 
        Mojo.Log.info("getAccountInfo success, Account="+JSON.stringify(r));
    },
    onFailure: function(r) { 
        Mojo.Log.info("getAccount failure, err="+JSON.stringify(r));
    }  
});

Example Output

Account= 
{
   "result":{
      "_kind":"com.palm.account:1",
      "_id":"2+31",
      "_rev":258,
      "_sync":true,
      "beingDeleted":false,
      "capabilityProviders":[
         {
            "_id":"2+32",
            "capability":"CONTACTS",
            "id":"com.palm.palmprofile.contacts",
            "db_kinds":{
               "contact":"com.palm.contact.palmprofile:1"
            }
         },
         {
            "_id":"2+33",
            "capability":"CALENDAR",
            "id":"com.palm.palmprofile.calendar"
         },
         {
            "_id":"2+34",
            "capability":"TASKS",
            "id":"com.palm.palmprofile.tasks"
         },
         {
            "_id":"2+35",
            "capability":"MEMOS",
            "id":"com.palm.palmprofile.memos"
         },
         {
            "_id":"2+36",
            "capability":"MESSAGING",
            "id":"com.palm.palmprofile.sms",
            "capabilitySubtype":"SMS",
            "loc_name":"SMS Account",
            "loc_shortName":"Text",
            "icon":{
               "loc_32x32":"\/usr\/palm\/public\/accounts\/com.palm.palmprofile\/images\/sms-32x32.png",
               "loc_48x48":"\/usr\/palm\/public\/accounts\/com.palm.palmprofile\/images\/sms-48x48.png",
               "splitter":"\/usr\/palm\/public\/accounts\/com.palm.palmprofile\/images\/sms-32x32.png"
            }
         }
      ],
      "templateId":"com.palm.palmprofile",
      "username":"Dr. Skipped Firstuse",
      "loc_name":"Palm Profile",
      "icon":{
         "loc_32x32":"\/usr\/palm\/public\/accounts\/com.palm.palmprofile\/images\/mypalm-32x32.png",
         "loc_48x48":"\/usr\/palm\/public\/accounts\/com.palm.palmprofile\/images\/mypalm-48x48.png"
      }
   }
}

 


modifyAccount

Can be used to change Account object properties including capabilities. Properties are overwritten.

If you add or delete a capability, the capability's Synergy service onEnabled method is called.

Syntax

{
    "accountId"  : string,
    "object"     : any
}

Parameters

Argument Required Type Description
accountId Yes string db8 account ID.
object Yes any Account properties and new values.

Returns

{
    "returnValue"  : boolean,
    "errorCode"    : string,
    "errorText"    : string   
}
Argument Required Type Description
returnValue Yes boolean true (success) or false (failure)
errorCode No string Returned on failure.
errorText No string Returned on failure. Text describing error.

Example

this.controller.serviceRequest("palm://com.palm.service.accounts/", {
    method: "modifyAccount",
    parameters: {
        "accountId":"2+Ph",
        "object": {"username":"ChuckWagon99", "alias": "huggybeer"}},
    onSuccess: function(){ 
        Mojo.Log.info("modifyAccount success"); 
    },
    onFailure: function(e) { 
        Mojo.Log.info("modifyAccount failure err = "+JSON.stringify(e)); 
    }        
});

 


Synergy Service

A Synergy service that interacts with the Account service needs to implement a number of callbacks that are invoked to validate login or when an account object in db8 storage is created or altered. These are named in the Synergy service's Account template file that the Account service reads on start-up. The Account service invokes these callbacks to validate credentials and notify the Synergy service about account creation or modification.

Note: Third-party services that interact with the Account Manager are required to be packaged (via palm-package) with an account-template.json file containing a template object along with accompanying metadata such as account icons and localized text.

Most Synergy services will want to store account-wide configuration data upon account creation, and clean up that data upon deletion. Creation is not the time to start syncing, and deletion is not the time to stop syncing.
When a capability is enabled, Synergy services should start syncing and schedule future syncs with the Activity Manager. When a capability is disabled, Synergy services should stop syncing, delete associated data, stop future syncs, and delete sync state.

Except where noted, all callbacks are per-capability, meaning that you can either elect to have one capability provider handle everything, or each capability provider can implement its own behaviors (or a mix of the two).

For each account capability, you can have the same or different callbacks. See the capability data type for required capability implementation fields.

Synergy Service Configuration Objects

Validators and custom validation UI can emit a configuration object that can be used to contain server settings and other account-wide, capability-independent configuration data. Unlike credentials, this is not kept in encrypted storage. Synergy services can read this data to know how to sync and validators and custom validation UI can emit new values to modify this data when the user changes login info.

Synergy services should use this for data that needs to persist even after a capability has been disabled (in case it is ever re-enabled), and delete it when the associated account is deleted (onDelete is called). Configuration data should not be used to store sync state or other information that should be deleted when a capability is disabled.

Synergy services are expected to persist configuration data when they are passed in to onCreate and clean them up in onDelete. Multiple services supporting different capabilities for a single account should cooperate in managing configuration objects—either each service could maintain its own portion, or one service could maintain it all.

Required Directory Structure

Synergy services should use the following hierarchy to organize device files. The root is assumed to be the first party root ("/usr/palm/public/") or third-party root ("/media/cryptofs/apps/usr/palm/accounts").

com.x.y/
    com.x.y.json
    images/
        xy-32x32.png
        xy-48x48.png
    resources/
        es_US/
            com.x.y.json (localized complete copy of base .json file)
            images/ (for localized images)
                xy-32x32.png
                xy-48x48.png

Account Manager Invoked Synergy Service Callbacks

Note that the names listed below are NOT the names of methods your Synergy service implements, they are field names in a capability object. Bus address and method names are the value for these fields, which can be anything you want.

 


onCapabilitiesChanged

The Account Manager calls this Synergy service method when an account's capability (email, blogging, contacts, etc.) is enabled or disabled. This can happen during initial account creation or when an account is subsequently modified (createAccount or modifyAccount). The new state of enabled capability providers is passed. This is useful for templates where a single unified Synergy service handles all syncing; in that case, it's easier to re-do all syncing in one step rather than using multiple 'onEnabled` handlers.

Syntax

{
   "accountId" : string,
   "capabilityProviders" : [
      {
         id      : string,
         enabled : boolean
      }
   ]
}

Parameters

Argument Required Type Description
accountId Yes string db8 account ID.
capabilityProviders Yes array of inline objects Array of object identifying capabilities and if they are enabled or disabled.
id Yes string Capability ID, i.e., "com.palm.facebook.calendar".
enabled Yes boolean Is capability enabled or disabled flag.

Returns

{
    returnValue : boolean
}
Argument Type Description
returnValue boolean true (success) or false (failure)

 


onCreate

The Account Manager calls this Synergy service method when an account is created. After this, the Account Manager calls the Synergy service's
onCapabilitiesChanged and onEnabled methods for each capability. When called, these handlers should save any passed configuration information.

Note that onCreate is not called again for restored accounts as it is assumed the data has been recreated from backup. Therefore, any onCreate persisted data must be backed up to restore the account properly.

Syntax

{
    "accountId" : string,
    "config"    :  any
}

Parameters

Argument Required Type Description
accountId Yes string db8 account ID.
config No any Opaque configuration objects containing any information the Synergy service wants such as IP addresses, ports, etc.

Returns

Argument Type Description
returnValue boolean true (success) or false (false)

 


onDelete

The Account Manager calls this when an entire account is being deleted. All capability providers that declared a handler are called. Handlers should delete any account-wide configuration. To proceed, all onDelete calls must succeed.

Syntax

{
    "accountId" : string
}

Parameters

Argument Required Type Description
accountId Yes string db8 account ID.

Returns

Argument Type Description
returnValue boolean true (success) or false (failure)

 


onEnabled

The Account Manager call this Synergy service method when a capability is enabled or disabled. When enabled, notified Synergy services should start a sync and schedule future syncs. When disabled, notified Synergy services should disable syncing and delete associated data. Account-wide configuration should remain on disk, and only deleted when onDelete is called.

Syntax

{
    "enabled"              : boolean,
    "accountId"            : string,
    "capabilityProviderId" : string
}

Parameters

Argument Required Type Description
enabled Yes boolean Capability enabled flag.
accountId Yes string db8 account ID.
capabilityProviderId Yes string Capability Provider ID, i.e., "com.palm.facebook.calendar"

Returns

{
    "returnValue" : boolean
}
Argument Type Description
returnValue boolean true (success) or false (failure)


validator

This API is called to validate a user's login (username and password). Typically, this is done over the cloud. It can return user credentials (passwords, authentication tokens) for an account and configuration information (i.e., server name, port, etc.). Credentials and configuration information can then be used in creating a localized user account object.

Validators should not modify existing account state.

Syntax

{
   "username"   : string,
   "password"   : string,
   "templateId" : string,
   "config"     : any array,
   "accountId"  : string
}

Parameters

Argument Required Type Description
username Yes string User name.
password Yes string Password.
templateId No string ID of the template file (i.e., "com.palm.google"). See the Template data type for more information on this file.
config No any array Array of opaque configuration objects.
accountId No string Only passed if modifying existing credentials.

Returns

{
   "returnValue" : boolean,
   "errorCode"   : string,
   "errorText"   : string,
   "templateId"  : string,
   "username"    : string,
   "alias"       : string,
   "credentials" : any,
   "config"      : any
}
Argument Required Type Description
returnValue Yes boolean true (success) or false (failure).
errorText No string Returned if validation fails and returnValue is false.
errorCode No string Returned on failure. Has the form: "errInvalidParamater", for example: "errFileNotFound".
templateId No string Returned if changing.
username No string Returned if changing.
alias No string Optional replacement for the account name, defaults to template's "loc_name".
credentials No any Array of opaque, named credentials objects.
config No any Amended opaque config objects (only if changing).

Example

Parameters

{
   "username":"HoLeeSmokes",
   "password":"Batman",
   "accountId":"2+Qn",
   "templateId":"com.palm.service.sample.contacts"
}

Return

{
   "returnValue":true,
   "templateId":"com.palm.service.sample.contacts",
   "credentials":{
      "common":{
         "secret":"shhhh",
         "authToken":"xxxToken7&%"
      }
   },
   "config":{
      "server":"sample.com",
      "port":443
   }
}

 


Synergy Service Error Codes

The following table contains a set of common, standardized error codes that Synergy services should return. All of the codes are localized on the UI side. If a condition does not match any of these error codes, a Synergy service should return:

{
    "errorCode": UNKNOWN_ERROR,
    "errorText": "<English error description message>"
 }
 

The UI ignores errorText if there is a UI-localized errorCode version and is communicated mostly for debugging purposes.

Error Number Description
UNKNOWN_ERROR -3141601 Generic fallback error.
401_UNAUTHORIZED -3141602 Same as HTTP 401: Invalid credentials.
408_TIMEOUT -3141603 Same as HTTP 408: Request timeout.
500_SERVER_ERROR -3141604 Same as HTTP 500: General server error.
503_SERVICE_UNAVAILABLE -3141605 Same as HTTP 503: Server is (temporarily) unavailable.
412_PRECONDITION_FAILED -3141606 Same as HTTP 412: Precondition failed. The client request is not suitable for current configuration.
400_BAD_REQUEST -3141607 Same as HTTP 400. Bad request.
HOST_NOT_FOUND -3141608 Host not found.
CONNECTION_TIMEOUT -3141609 Connection timeout.
CONNECTION_FAILED -3141610 Miscellaneous connection failed.
NO_CONNECTIVITY -3141611 No connectivity.
SSL_CERT_EXPIRED -3141612 SSL certificate expired.
SSL_CERT_UNTRUSTED -3141613 SSL certificate not trusted.
SSL_CERT_INVALID -3141614 SSL certificate invalid.
SSL_CERT_HOSTNAME_MISMATCH -3141615 SSL certificate hostname mismatch.
DUPLICATE_ACCOUNT -3141616 Attempted, but refused to add a duplicate account.
UNSUPPORTED_CAPABILITY -3141617 Operation failed due to an unsupported capability. This error maps to a specific, user-friendly message.

Example

If credentials are invalid, a validator method should return the following to the UI:

{
    "returnValue": false,
    "errorCode": 401_UNAUTHORIZED
}

Note that since this is a standardized error, errorText is not required.

 


Custom Validator

Most account templates can utilize the standard username/password Accounts UI when logging in. If not, the Accounts Framework allows template authors to specify a custom UI to display in lieu of the standard login UI. The custom UI is integrated into the account creation flow using Cross-App Push, and the custom validation UI is expected to return a result using popScene(result).

Custom Validator Checklist

  • Specify a CustomValidatorObj in place of a bus address string for your "validator" in your account template. The appId and name must refer to an app and scene.

The validation scene must accept as input the following arguments:

      MyAssistant( { initialTemplate, allTemplates } )

"initialTemplate" is optional and is only passed in if known. "allTemplates" is the list of known account templates as returned by "com.palm.service.accounts/listAccountTemplates"

  • The validation scene must determine the following:

  • The template to use when creating the account.
  • The username is unique for this template.
  • Handle optional config from the UI.
  • The default validator login result (including credentials and, optionally, config).
  • Login results for all other validators (because the password is not returned, custom validation UI must do this). You can use AccountsUI.multiLogin() for this:

        // returns a future which will be done after validating the login against an
        // array of validator service methods.  The final result looks like:
        //
        // { defaultResult: &lt;SINGLE_RESULT&gt;, otherResults: [ SINGLE_RESULT, ... ] }
        //
        // (where SINGLE_RESULT=
        // { id: &lt;validator id>, result:&lt;Validator Response&gt; -OR- exception: &lt;Validator Error&gt; }
        // )
        //
        // If the default validator fails, the Future will error out. Other failures are
        // individually reported in 'otherResults'.
    
    
  • Validation UI should return a result that looks like this:

    {
        template: Template object,
        username: string,
        defaultResult: ResultObj,
        otherResults: array of ResultObj (optional),
        config: &lt;dictionary of server settings in addition to those in ResultObjs&gt;
    }
    
    

Where TemplateObj is a Template object as returned by listAccountTemplates and ResultObj is:

    {
        item: {
                id: string (capability provider ID),
               validator: string (bus address of validator)
              },
        result: { (response from the validator call)
                 returnValue,
                 credentials,
                 config
                }
   }