Custom authentication methods in Odoo HTTP controllers

By default, Odoo HTTP controller methods can use one of three authentication methods: user, public or none. If the method is not explicitly defined, it is user by default.

What is interesting, is that it is possible to define your own authentication methods by defining a class method on the ir.http abstract model named _auth_method_<method name>. I've found one such custom authentication method in the calendar addon.

Adding a custom auth method

The following example is made using Odoo 11.0 Community Edition running on localhost port 8069 with demo data installed.

The following example is intentionally simplified. Do not use as is.

To illustrate, let's add a new authentication method named custom which will set the user to SUPERUSER_ID if an Authorization header with the value 42 is provided in the request:

class IrHttp(models.AbstractModel):
    _inherit = 'ir.http'

    @classmethod
    def _auth_method_custom(cls):
        auth_header = request.httprequest.headers.get('Authorization')
        if auth_header and tools.consteq(auth_header, '42'):
            if not request.session.uid:
                request.uid = SUPERUSER_ID
            # Valid user session exists, decide what to do here.
            else:
                request.uid = request.session.uid
        else:
            raise exceptions.AccessDenied()

If the user fails to authenticate in the body authentication method, one should raise an exception, which will essentially fail the request. If authentication succeeds, request.uid should be set to the database ID of the user who just authenticated.

Now, to use it in an HTTP controller:

class Controller(http.Controller):

    @http.route('/custom_auth/test', type='json', auth='custom')
    def custom_auth_test(self):
        return {
            'uid': request.uid,
        }

Calling the endpoint:

$ curl -X POST 'http://localhost:8069/custom_auth/test' -H 'Content-Type: application/json' -H 'Authorization: 42' --data '{"params": {}}'
{"id": null, "result": {"uid": 1}, "jsonrpc": "2.0"}

This example is available in full form here.

Considerations

It seems custom authentication methods will not work in a multi-database environment while a database is not selected, because only none authenticated methods are collected in non-db routing mode.

Also, care should be taken to handle the case where a valid session_id cookie is passed, to avoid mixing user IDs.