Add support for storing per-user OAuth2 tokens
Overview
Expand API support for OAuth2 tokens to support transactional/interactive/short-term use-cases.
See https://docs.civicrm.org/dev/en/latest/framework/oauth/#model-token for more discussion of per-system tokens vs per-user tokens.
Example use-case
- Click on Import Contacts.
- For a source, choose Google Drive
- Run OAuth2 "Authorization Code" flow to get an access token. Store the access-token just for this user.
- Proceed to use the token for choosing+reading a spreadsheet.
Current behavior
When running the "Authorization Code" flow, the only available storage option is OAuthSysToken
:
$start = civicrm_api4('OAuthClient', 'authorizationCode', [
'where' => [['id', '=', 123]],
'storage' => 'OAuthSysToken',
])->single();
This storage is appropriate for long-term system-level services like CiviMail bounce checking - but not for transactional/interactive usage. Ex:
- Suppose you implement the Google Drive spreadsheet example using
OAuthSysToken
. - Suppose you want to allow Alice and Bob to both import from Google Drive. Thus, both can read/write
OAuthSysToken
records. - Alice imports one spreadsheet, so it creates an
OAuthSysToken
- Bob imports one spreadsheet, so it creates an
OAuthSysToken
- Alice can see Bob's token just as well as her own; and vice-versa. This allows them to go poking at each other's data.
Proposed behavior
Add an API OAuthUserToken
which works like OAuthSysToken
$start = civicrm_api4('OAuthClient', 'authorizationCode', [
'where' => [['id', '=', 123]],
'storage' => 'OAuthUserToken',
])->single();
Except that it defines clearer ownership (associating the token with the current user) and expiration mechanism (so that we don't hold on to it forever).
Some possible implementations:
-
OAuthUserToken extends BasicEntity
. Use data-storage in$_SESSION
orCivi::cache('session')
. This makes it invisible to other users, and it provides an end-of-life plan for the token. -
OAuthUserToken extends DAOEntity
. Use data-storage in MySQL (and mandatory filters/cleanups to deal with ownership and expiration).