One feature of Lotus Expeditor is the Accounts framework. The Accounts framework allows users to setup accounts to remote systems which can be used to login to those systems. Accounts have properties like name, server, credentials, login type and others including custom properties.
Since Lotus Notes 8 Standard is built on Lotus Expeditor, Lotus Notes 8 has the Accounts framework as well. In fact, the Accounts framework is tightly integrated into Notes 8 such that accounts are stored inside your Personal Address Book (PNAB).
Behind the scenes, Lotus Expeditor’s Accounts framework offloads some of the core work to an adapter class, and Lotus Notes 8 has an adapter class for reading and writing accounts in the PNAB. This adapter approach allows the various products built on top of Lotus Expeditor (Notes 8, Sametime, Symphony) to have different low-level implementations for accounts.
Opening URLs in code
So let’s say we have a plugin and we want to make a HTTP call to some remote server that requires authentication. One function of the Accounts framework is to automatically handle the authentication part for you. In fact, you don’t even need to call the Accounts framework for this to happen.
When you open a URL using java.net.URL.openConnection(), Lotus Expeditor will check if any accounts exist which can handle that URL. This is based on the server name defined in each account. Once an account is found, the credentials will be applied to the HTTP request based on the authentication type defined in the account.
For example, if an account is defined for “http://myservice.acme.com” with HTTP Basic Authentication, Lotus Expeditor will automatically add the basic auth header with the account’s name and password to the HTTP request.
Account selection examples
Assume we start with the following accounts:
|profiles [linked to Connections]||http://connections.acme.com/profiles|
|profiles_ssl [linked to Connections]||https://connections.acme.com/profiles|
Activities plugin example
If Activities is opened on the Notes sidebar, the Activities plugin first requests the following URL using java.net.URL.openConnection():
The underlying implementation for java.net.URL.openConnection() attempts to find an account that can handle the URL. The requested URL is compared against the known accounts. If no match was found, the URL is stripped down until a match is found:
- https://connections.acme.com/activities/service/atom/version --> no match
- https://connections.acme.com/activities/service/atom/ --> no match
- https://connections.acme.com/activities/service/atom --> no match
- https://connections.acme.com/activities/service/ --> no match
- https://connections.acme.com/activities/service --> no match
- https://connections.acme.com/activities/ --> no match
- https://connections.acme.com/activities --> match for Activities account
When the requested URL is reduced to "https://connections.acme.com/activities", it matches the server in the "Activities" account. This account's credentials are used for the request.
MyPlugin plugin example
Custom plugin “MyPlugin” is started, and MyPlugin plugin first requests the following URL:
Lotus Expeditor / Lotus Notes attempts to find an account to handle the request:
- https://connections.acme.com/profiles/atom/profileService.do --> no match
- https://connections.acme.com/profiles/atom/ --> no match
- https://connections.acme.com/profiles/atom --> no match
- https://connections.acme.com/profiles/ --> no match
- https://connections.acme.com/profiles --> match for 2 accounts [profiles_ssl, MyPluginAccount]
In this case, 2 accounts satisfy the requested URL. When multiple accounts apply, the chosen account is ambiguous. In my test, "profiles_ssl" was used, not “MyPluginAccount”. On another person's machine, “MyPluginAccount” may have been selected.
Avoid multiple accounts covering the same server
As shown in the MyPlugin example above, the behavior is undefined (and unsupported) when multiple accounts cover the same HTTP request made by URL.openConnection(). Users and developers should be avoid this case.