Add support for storing per-user OAuth2 tokens
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.
- 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.
When running the "Authorization Code" flow, the only available storage option is
$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
- Suppose you want to allow Alice and Bob to both import from Google Drive. Thus, both can read/write
- Alice imports one spreadsheet, so it creates an
- Bob imports one spreadsheet, so it creates an
- 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.
Add an API
OAuthUserToken which works like
$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
Civi::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).