Rationale
There are APIs that Tryton may need to connect to that require oauth2 authorisation. To avoid re-implementing the common parts of this process it would be good if there were classes/methods/wizards/etc available that provided the common functionality.
This would be helpful when adding Support for UK HMRC Making Tax Digital (MTD), as it provides a RESTful API that requires oauth2 authorization.
There also appears to be an API called PISTE that uses oauth2 which could also use these common parts.
Proposal
I am not too sure the best way of doing this, this is one suggestion which I think may work, but I would welcome any improvements, or better / alternative ways of doing this.
Add a new oauth2
module that will provide:
-
OAuth2APIProvider
- A model that represents the company or organisation that provides the API service. -
OAuth2API
- A model that represents the API itself.This would contain the properties of the API, such as the Base URL, Token Endpoint, Redirect URL, Authorization URL, etc. There would be a Many2One to the
OAuth2Provider
. The records in this model would describe the provider’s Production, Testing, etc API. -
OAuth2APIUserMixin
- A mixin applied to models whose records are API Users.This mixin would be added to models such as
User
,Company
orEmployee
, depending on the provider or API. It would provide a means of allowing the selection of the API to use with the provider, and a method that would return the session for the API User’s currently selected API. -
OAuth2Application
- Represents the Tryton application and implements theOAuth2APIUserMixin
.Used with the backend application flow when the API User is the Tryton application itself.
-
OAuth2Session
- Details about an API User’s connection to anOAuth2API
.This model would store the details about a connection to the API that need to be saved across requests. There would be a
Reference
to the API User, and aMany2One
to theOAuth2API
. Details about the session, such as the Token, State (used to mitigate CSRF, and to find the session after authorization - see below) and any Errors related to the connection would also be stored here.A
classmethod
would be available to get a session for the Provider, API User model, and scope. This would use the current context to work out which individualCompany
,User
, etc. the session should be for.Each
OAuth2Session
would provide a property / getter which would return the requests_oauth2lib session object which is then used to call methods on the API. -
OAuth2APIEndpoint
- This class would represent an endpoint in the API.It would have properties to define the endpoint, provider, http method, API User model, scope, etc. The objects created from this class would be callable, and calling them would use the
OAuth2Session
.get
classmethod to get an appropriate session to use to send the request to the api and get the result. The result would then be returned to the caller, or an exception thrown if the call to the API couldn’t be done. -
OAuth2WizardMixin
(or extension to Wizard class).This would help when creating wizards that make calls to the OAuth2 API. It would catch any
OAuth2Unauthorized
exceptions that are thrown when making calls to the API, and would add some states that guide the user through, or automatically perform, the authorization process.To authorize the user, one of the states would send a URL Action to the client that will open the authorization endpoint in the user’s browser. The user will authenticate with the service and grant the appropriate authority. When submitted this will then send the user’s browser to the
redirect_url
which must be setup to point to their trytond server. A route at thisredirect_url
will get the request and use the code from the authorization along with the state to get and save the OAuth2 token in theOAuth2Session
.Now authorized, the wizard could then send the user back to the state where the
OAuth2Unauthorized
execption occurred so they could try again, as now the request should be successful.A wizard derived from this mixin or extension could then be used for most of the calls to the API.