OAuth

The Simple OAuth module is used to provide an OAuth2 standard authorization server.

For documentation on using and authenticating with the farmOS API see API.

Providing OAuth Scopes

OAuth Scopes define different levels of access. The farmOS server implements scopes that represent individual roles or permissions. Users will authorize clients with one or more scopes that determine how much access they have to data on the server.

OAuth scopes are provided to the server using scope provider plugins. Each scope provider determines how scopes are implemented and created. The OAuth server must choose a single scope provider to provide all the scopes necessary for the server's authorization needs. All scopes use the same configuration and provide the same features regardless of the scope provider.

The Simple OAuth module provides two scope providers: static and dynamic. The static scope provider implements scopes as a yaml plugin that must be provided by modules and prevents scopes from being modified. The dynamic scope provider implements scopes as a config entity and allows scopes to be created and modified via the UI. Modules can provide dynamic scopes as well but there are no guarantees that these scopes will remain unmodified.

farmOS defaults to using the static scope provider. This allows modules providing OAuth scopes to guarantee that their scopes exist unmodified within the server. The farmOS administrator can change to using the dynamic scope provider if necessary, but may need to re-create any static scopes that are needed for integrations provided by other modules.

The farmOS Default Roles module provides a static OAuth scope for each of the default roles: farm_manager, farm_worker, and farm_viewer.

Scope Configuration

All scopes use the same configuration and provide the same features regardless of the scope provider:

  • Scopes must provide a name to uniquely identify the scope
  • Scopes must provide a description
  • Scopes must specify if they are an umbrella scope. Umbrella scopes are only used as parent for child scopes to reference and do not specify a granularity.
  • Scopes must configure which grant_types they allow. Each grant type can include an optional description to describe how the scope is used in the context of each grant type.
  • Scopes can optionally specify a parent scope that the scope is a part of. When the parent scope is requested, all of its child scopes are granted as well.
  • Scopes must specify a granularity if they are not an umbrella scope. This value must be equal to permission or role. The scope must provide a single value for the permission or role it is associated with.

This configuration is most easily demonstrated with static scopes that are provided in a module.oauth2_scopes.yml plugin file.

"scope:name":
  description: string (required)
  umbrella: boolean (required)
  grant_types: (required)
    GRANT_TYPE_PLUGIN_ID: (required: only known grant types)
      status: boolean (required)
      description: string
  parent: string
  granularity: string (required: if umbrella is FALSE, values: permission or role)
  permission: string (required: if umbrella is FALSE and granularity set to permission)
  role: string (required: if umbrella is FALSE and granularity set to role)

An example of the static farm_manager scope provided by the farmOS Role Roles mdoule:

farm_manager:
  description: 'Grants access to the Farm Manager role.'
  umbrella: false
  grant_types:
    authorization_code:
      status: true
    refresh_token:
      status: true
    password:
      status: true
  granularity: 'role'
  role: 'farm_manager'

Providing OAuth Clients

OAuth clients are modeled as "Consumer" entities (provided by the Consumers module. To create integrations with farmOS a consumer entity must be created that identifies the integration and configures the OAuth Client for the desired authorization behavior.

The core farm_api_default_consumer module provides a default client with client_id = farm that can use the password and refresh_token grant. You can use this client for general usage of the API, like writing a script that communicates with your farmOS server, but it comes with limitations.

Client Configuration

Standard Consumer configuration:

  • consumer.label - A label used to identify the third party integration.
  • consumer.client_id - An optional client_id machine name to identify the consumer. The simple_oauth module uses a UUID by default, but a machine name makes it easier to identify clients across multiple farmOS servers.
  • consumer.secret - A client_secret used to secure the OAuth client.
  • consumer.confidential - A boolean indicating whether the client secret needs to be validated.
    • Most farmOS third party integrations will disable this. Otherwise the same client_secret must be configured on all farmOS servers, or the third party must keep track of a different secret for each server. This challenge is due to the nature of farmOS being a self-hosted application.
  • consumer.user_id - When no specific user is authenticated Drupal will use this user as the author of all the actions made by this consumer.
    • This is only the case during the Client Credentials authorization flow.
  • consumer.grant_types - A list of the grant types that the client allows.
  • consumer.scopes - A list of default scopes that will be granted for this client if no scopes are requested during the authorization flow. No scopes will be granted that the user does not have access to.
  • consumer.access_token_expiration - The lifetime of access tokens in seconds.
  • consumer.refresh_token_expiration - The lifetime of refresh tokens in seconds.
  • consumer.redirect_uri - The URI this client will redirect to when needed.
    • This is used with the Authorization Code authorization flow.
  • consumer.allowed_origins - Define any allowed origins the farmOS server should allow CORS requests from. This is required for any API integrations that will run in the browser.
  • consumer.third_party - Enable if the Consumer represents a third party.
    • Users will skip the "grant" step of the authorization flow for first party consumers only.