/oauth2-clientd

OAuth2 client caching daemon

Primary LanguagePythonGNU General Public License v2.0GPL-2.0

oauth2-clientd

oauth2-clientd is a script to manage OAUTH2 tokens for terminal or headless Mail User Agents (MUAs) like fetchmail or mutt.

It can obtain a refresh token, securely store it, periodically update it, and return access tokens on-demand via either a plaintext file or UNIX socket.

Installation

You will need the following dependencies:

$ pip3 install --user oauthlib requests-oauthlib python-daemon

Then to install:

$ python3 setup.py install --user

Getting started

To get started, you'll need to generate a refresh token.

$ oauth2-clientd -a -c <clientid> [-P <provider>] /path/to/sessionfile

If the sessionfile exists, it will be not overwritten without --force.

If left unspecified, the default provider is Microsoft Office 365.

You'll be prompted for two things:

  • The secret for the clientid, if any.
  • The password for the private key (with confirmation)

Then you'll be presented with a URL to follow in your browser to authenticate to your provider.

If the provider is configured to redirect to localhost, an HTTP listener will be started on a random port. Otherwise, you'll need to copy-and-paste the authorization URL the provider sends as a response. If your MUA is running on a remote system, you can specify the port to use for the listener with -p <port> to allow an SSH tunnel to be used to forward the response to the script.

Once the refresh token is obtained, oauth2-clientd will wait until interrupted, refreshing the refresh token 5 minutes before it expires.

Output

By default, oauth2-clientd will refresh the token and output an access token on stdout. Your MUA will probably either use a command to fetch a new access token or expect the access token to be written to a plaintext file on disk.

oauth2-clientd exports tokens in two ways:

The following options can be used to start up an HTTP listener on the specified UNIX socket. If the socket exists it will be removed and replaced.

$ oauth2-clientd -s /path/to/socket /path/to/sessionfile

Your MUA can be configured to retreive the access token with a simple command:

$ curl --unix-socket /path/to/socket http://localhost

If your client requires a plaintext file, the following command will write out such a file each time the token is refreshed:

$ oauth2-clientd -f /path/to/file /path/to/sessionfile

Both options can be used at the same time but each can only be specified once.

Background

The script can be daemonized using the -D option which takes the path to a logfile as an argument.

$ oauth2-clientd [other options] -D /path/to/logfile /path/to/sessionfile

Security

The tokens are kept secure on disk using AES encryption. Each time the tokens are written, a new key is generated, and encrypted with the RSA public key generated during the authorize step. The password for the private key is used during startup to unlock the saved tokens and is unused after that. The refresh token is kept in memory but never written to disk in unencrypted form. The access token is available in plaintext but should be configured with a short expiration time.

Configuration

With version 0.7, oauth2-clientd uses external configuration files to setup provider definitions. The defaults have remained the same and are shipped in a package resource file named builtin-providers.conf. This file, /etc/oauth2-client.conf, and ~/.config/oauth2-clientd/oauth2-clientd.conf will be read in order and each is optional. Additional configuration files can be specified on the command line via the -C <filename>. The defaults can be cleared by using -C "" or -C /dev/null and subsequent uses of -C will again be additive.

It is possible to extend provider definitions by inheriting from existing ones, adding or clearing options as needed. The most common use for this is to specify site- or user- specific client IDs and optional client secrets to existing profile definitions. To clear an option, assign it an empty value.

Format

The configuration file format is the familiar .INI file format used in many projects. The DEFAULT section defines the default provider definition using the provider option. Other sections define providers using the name of the section as the name of the provider. The options consumed by this tool are as follows:

  • authorize_endpoint: The URI to use to obtain an authorization code.
  • token_endpoint: The URI to use to obtain tokens using the authorization code or the refresh token..
  • redirect_uri: The URI to redirect the client to after successfully obtaining the refresh token. For this tool to work properly, it must be: http://localhost
  • sasl_method: The SASL method used. Will be XOAUTH2 or OAUTHBEARER.
  • scope: The scopes associated with the token. These will be site and resource specific. Please reference the documentation for the service you are using to obtain proper scopes for the resource being accessed.

For a full provider definition, reference the provided builtin-providers.conf file.

Example

The following example, using contrived credentials, extends the Office365 definition for your site and uses it as the default provider. These configuration sections can be added to a one of the known locations shown above or in a new file used via -C.

[DEFAULT]
provider = site-o365

[site-o365]
inherits = office365
client_id = e9b20c6d-641d-4cf4-878d-fe78ff79746f
client_secret =

Client IDs

A client ID and optional secret is required for oauth2-clientd to successfully authenticate via OAUTH2.

Office 365

For corporate Office 365, your administrator will have to add a client ID to your organization's Active Directory instance. Once a client ID and optional client secret have been obtained, they can be specified using the -c <clientid> option or by adding a client_id= <clientid> option to a provider definition in a known configuration file. See Configuration above.

Outlook.com personal accounts

Outlook.com personal accounts are not supported yet and need more research.

Gmail and Google Workspace

For personal Gmail accounts, you'll need to register this application as a valid application in the Google Cloud Platform Console. The same applies to Workspace domains but your account must have administrative privileges to do it.

If you haven't used this service prior to configuring these Client IDs, you'll have to accept the terms of service and create a new project (or use an existing one).

Once the project is created, select it and go to the APIs pane.

There, you'll need to configure the "OAuth Consent Screen" first.

You'll need to choose a user type. External will work for the purposes of setting up the client IDs for this use. Next you'll enter a workflow:

  • (1) OAuth Consent Screen

    • App Information

      • App name: <oauth2-clientd> -- This is for your own reference
      • User support email: <this will be a pull down of your registered email addresses or groups>
      • App logo: (optional)
    • App domain (optional)

    • Authorized domains (optional)

    • Developer contact information <same email address as above>

  • (2) Scopes

    • Click on Add or remove scopes
    • Manually add scopes
      • https://mail.google.com
  • (3) Test Users

    • Click on Add users
    • Add your gmail address

Next select the Credentials pane.

Click + CREATE CREDENTIALS and select OAuth Client ID. The application type will be Web Application. Once you select it, a number of other fields will appear. The Name field is for you to be able to identify the client ID later and can be whatever you like. Click + Add URI under the Authorized redirect URIs heading and add http://localhost before clicking Create. Once you've created it, it will display the client ID and secret. These will be available via the Credentials console for you to reference in the future.

Once you have the client ID and secret, you can establish your tokens using

$ oauth2-clientd -P google -c <clientid> -a /path/to/sessionfile

and then following the instructions under Getting Started. The client ID can also be specified in a new provider section in a known configuration file. See Configuration above.