Authentication
farmOS includes an OAuth2 Authorization server for providing 1st and 3rd party
clients access to the farmOS API. Rather than using a user's username and
password to both authorize and authenticate a request, OAuth2 requires
users to complete an authorization flow that generates an access_token
to be used for authentication. Access tokens are provided to both 1st and
3rd party clients who wish to access the server's protected resources. Clients
store the access token
instead of the user's credentials, which makes it a
more secure authentication method.
Read more about the OAuth 2.0 standards.
Client Libraries
The farmOS.py and farmOS.js client libraries use the OAuth2 protocol to interact with the farmOS API.
OAuth2 Bearer Tokens
Once you have an OAuth2 token, you can authenticate requests to the farmOS
server by including an Authentication: Bearer {access_token}
header.
OAuth2 Details
The OAuth protocol defines a process where users authorize 1st and 3rd party clients with scoped access to data on the server. The following describes the details necessary for using OAuth2 authorization with a farmOS server.
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.
The farmOS Default Roles module provides an OAuth scope for each of the default
roles: farm_manager
, farm_worker
, and farm_viewer
.
If you are creating an integration with farmOS, see the OAuth page of the farmOS module development docs for steps to create additional OAuth Scopes.
Clients
An OAuth Client represents a 1st or 3rd party integration with the farmOS
server. Clients are uniquely identified by a client_id
and can have an
optional client_secret
for private integrations. Clients are configured to
allow only specific OAuth grants and can specify default scopes
that are
granted when none are requested.
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.
If you are creating an integration with farmOS, see the OAuth page of the farmOS module development docs for steps to create an OAuth Client.
Authorization Flows
The OAuth 2.0 standards outline 3 Oauth2 Grant Types to be used in an OAuth2 Authorization Flow - They are the Authorization Code, Client Credentials and Refresh Token Grants. The Authorization Code and Refresh Token grants are the only Authorization Flows recommended by farmOS for use with 3rd party clients.
The Client Credentials Grant is often used for machine authentication not
associated with a user account. The client credentials grant should only be
used if a client_secret
can be kept secret. If connecting to multiple
farmOS servers, each server should use a different secret. This is
challenging due to the nature of farmOS being a self-hosted application.
The Password Credentials Grant is a legacy grant type that is no longer recommended. Only use the Password Credentials Grant if the client can be trusted with a farmOS username and password (this is considered 1st party). Even if the client is trusted, this grant type exposes the username and password and results in an increased attack surface. In most cases the Client Credentials Grant can be used with an OAuth client that is configured for each separate integration.
Authorization Code Grant
The Authorization Code Grant is most popular for 3rd party client authorization.
Requesting resources is a four step process:
First: the client sends a request to the farmOS server /oauth/authorize
endpoint requesting an Authorization Code
. The user logs in and authorizes
the client to have the OAuth Scopes it is requesting.
Copy this link to browser -
http://localhost/oauth/authorize?response_type=code&client_id=farm&scope=farm_manager&redirect_uri=http://thirdparty/api/authorized&state=p4W8P5f7gJCIDbC1Mv78zHhlpJOidy
Second: after the user accepts, the server redirects
to the redirect_uri
with an authorization code
and state
in the query
parameters.
Example redirect url from server:
http://thirdparty/api/authorized?code=9eb9442c7a2b011fd59617635cca5421cd089943&state=p4W8P5f7gJCIDbC1Mv78zHhlpJOidy
Third: copy the code
and state
from the URL into the body of a POST
request. The grant_type
, client_id
, client_secret
and redirect_uri
must
also be included in the POST body. The client makes a POST request to the
/oauth/token
endpoint to retrieve an access_token
and refresh_token
.
$ curl -X POST -d "grant_type=authorization_code&code=ae4d1381cc67def1c10dc88a19af6ac30d7b5959&client_id=farm&redirect_uri=http://thirdparty/api/authorized" http://localhost/oauth/token
{"access_token":"3f9212c4a6656f1cd1304e47307927a7c224abb0","expires_in":"10","token_type":"Bearer","scope":"farm_manager","refresh_token":"292810b04d688bfb5c3cee28e45637ec8ef1dd9e"}
Fourth: the client sends the access token in the request header to access protected
resources. The header is an Authorization header with a Bearer token:
Authorization: Bearer access_token
$ curl --header "Authorization: Bearer b872daf5827a75495c8194c6bfa4f90cf46c143e" http://localhost/api
Password Credentials Grant
NOTE: The Password Credentials Grant is a legacy grant type that is no longer recommended. Only use the Password Grant if the client can be trusted with a farmOS username and password (this is considered 1st party).
NOTE: The Simple OAuth Password Grant module must be enabled to use the password grant.
The Password Credentials Grant uses a farmOS username
and password
to
retrieve an access_token
and refresh_token
in one step. For the user, this
is the simplest type of authorization. Because the client can be trusted with
their farmOS Credentials, a users username
and password
can be collected
directly into a login form within the client application. These credentials are
then used (not stored) to request tokens which are used for authentication
with the farmOS server and retrieving data.
Requesting protected resources is a two step process:
First, the client sends a POST request to the farmOS server /oauth/token
endpoint with grant_type
set to password
and a username
and password
included in the request body.
$ curl -X POST -d "grant_type=password&username=username&password=test&client_id=farm&scope=farm_manager" http://localhost/oauth/token
{"access_token":"e69c60dea3f5c59c95863928fa6fb860d3506fe9","expires_in":"300","token_type":"Bearer","scope":"farm_manager","refresh_token":"cead7d46d18d74daea83f114bc0b512ec4cc31c3"}
second, the client sends the access_token
in the request header to access protected
resources. The header is an Authorization header with a Bearer token:
Authorization: Bearer access_token
$ curl --header "Authorization: Bearer e69c60dea3f5c59c95863928fa6fb860d3506fe9" http://localhost/api
Refreshing Tokens
The refresh_token
can be used to retrieve a new access_token
if the token
has expired.
It is a one step process:
The client sends an authenticated request to the /oauth/token
endpoint with
grant_type
set to refresh_token
and includes the refresh_token
,
client_id
and client_secret
in the request body.
$ curl -X POST -H 'Authorization: Bearer ad52c04d26c1002084501d28b59196996f0bd93f' -d 'refresh_token=52e7a0e12e8ddd08b155b3b3ee385687fef01664&grant_type=refresh_token&client_id=farm&client_secret=client_secret' http://localhost/oauth/token
{"access_token":"acdbfabb736e42aa301b50fdda95d6b7fd3e7e14","expires_in":"300","token_type":"Bearer","scope":"user_access","refresh_token":"b73f4744840498a26f43447d8cf755238bfd391a"}
The server responds with an access_token
and refresh_token
that can be used
in future requests. The previous access_token
and refresh_token
will no
longer work.