Update OAuth development docs

This commit is contained in:
Paul Weidner 2023-11-01 10:30:35 -07:00 committed by Michael Stenta
parent e53ccd5fa8
commit 48a55180d9
1 changed files with 98 additions and 37 deletions

View File

@ -5,22 +5,101 @@ to provide an [OAuth2 standard](https://oauth.net/2/) authorization server.
For documentation on using and authenticating with the farmOS API see [API](/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](https://www.drupal.org/project/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.
```yaml
"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:
```yaml
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](https://www.drupal.org/project/consumers) module. The `farm_api`
module provides a default client with `client_id = farm`. This can be used for
general usage of the API, but comes with limitations. To create a third party
integration with farmOS a `consumer` entity must be created that identifies
the integration and configures the OAuth Client authorization behavior.
[Consumers](https://www.drupal.org/project/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.
## Scopes
OAuth scopes define different levels of permission. OAuth clients are
configured with the scopes needed for the purposes of a specific integration.
With consumers, these scopes are implemented as Drupal Roles. This means that
OAuth clients interacting with farmOS over the API use the same permission
system as Users normally using the site.
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
@ -40,6 +119,13 @@ Standard Consumer configuration:
- `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
@ -48,28 +134,3 @@ Standard Consumer configuration:
- `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.
farmOS extends the `consumers` and `simple_oauth` modules to provide additional
authorization options on consumer entities. These additional options make it
possible to support different third party integration use cases via the same
OAuth Authorization server. They can be configured via the UI or when creating
a consumer entity programmatically.
Authorization options (all are disabled by default):
- `consumer.grant_user_access` - Always grant the authorizing user's access
to this consumer.
- This is how the farmOS Field Kit consumer is configured. If this is the
only option enabled, then the consumer will only be granted the roles
the user has access to.
- `consumer.limit_requested_access` - Only grant this consumer the scopes
requested during authorization.
- By default, all scopes configured with the consumer will be granted
during authorization. This allows users to select which scopes they want
to grant the third party during authorization.
- `consumer.limit_user_access` - Never grant the consumer more access than
the authorizing user.
- It is possible that clients will be configured with different roles
than the user that authorizes access to a third party. There are times
that this may be intentional, but this setting ensures that consumers
will not be granted more access than the authorizing user.