Galicea OpenID Connect Provider

OpenID Connect Provider for Odoo & OAuth2 resource server

This add-on allows Odoo to become an OpenID Connect Identity Provider (or just OAuth2 authorization server). The supported use-case is to allow several company-owned applications (possibly other Odoo instances) to reuse identities provided by Odoo, by becoming its OpenID Connect Clients. There is no technical reason not to allow third-party clients, but keep in mind that as is, there is no support for custom scopes (other than openid) and no permission is required from the user to share their identity with the client.

The add-on also provides OAuth2 token validation for use in custom API endpoints. This allows the clients to securely fetch data from Odoo.

Prerequisites

pip install -r galicea_openid_connect/requirements.txt

Client configuration

Simply go to OpenID Connect Provider menu to register a new client. Make sure that the Redirect URI exactly matches redirect_uri parameter your client is going to send. Copy generated Client ID and Client secret to configure your client.

You can use OpenID Connect Discovery to set up your client. The discovery document URL will be located at <odoo-base-url>/.well-known/openid-configuration and it looks like this:

{
    "authorization_endpoint": "<odoo-base-url>/oauth/authorize",
    "grant_types_supported": [
        "authorization_code",
        "implicit"
    ],
    "id_token_signing_alg_values_supported": [
        "RS256"
    ],
    "issuer": "<odoo-base-url>/",
    "jwks_uri": "<odoo-base-url>/oauth/jwks",
    "response_types_supported": [
        "code",
        "token",
        "id_token token",
        "id_token"
    ],
    "scopes_supported": [
        "openid"
    ],
    "subject_types_supported": [
        "public"
    ],
    "token_endpoint": "<odoo-base-url>/oauth/token",
    "token_endpoint_auth_methods_supported": [
        "client_secret_post"
    ],
    "userinfo_endpoint": "<odoo-base-url>/oauth/userinfo"
}

Configuring other Odoo instance/DB to be the client

Let's say that you want to allow users registered in your master.odoo.com Odoo instance to be able to log into client.odoo.com instance, without having to create a separate account.

To do that, simply install this module on master.odoo.com and add the client, using /auth_oauth/signin as a redirect_uri:

Now, in client.odoo.com:

  • install the auth_oauth add-on,
  • enable developer mode,
  • make sure that Allow external users to sign up option is enabled in General settings
  • add the following OAuth Provider data in the settings:
  • Now, the users of client.odoo.com will be able to login using new Login with Master link. In case they are already logged into master.odoo.com, all they need to do is to click it. Otherwise, they will be redirected to master.odoo.com to provide their credentials.

    Creating JSON APIs with OAuth2 authorization

    Along with the ID token, it's possible for the OpenID Connect Client to request access token, that can be used to authorize access to a custom JSON API.

    You can create such API in a way that is similar to creating regular Odoo controllers:

    # -*- coding: utf-8 -*-
    
    from odoo import http
    from odoo.addons.galicea_openid_connect.api import resource
    
    class ExternalAPI(http.Controller):
        @resource('/oauth/userinfo', method='GET')
        def userinfo(self, req, **query):
            user = req.env.user
            return {
                'sub': str(user.id),
                'name': user.name,
                'email': user.email
            }
    
    (note that this particular endpoint is bundled into galicea_openid_connect add-on). The client can then call this endpoint with either a header that looks like Authorization: Bearer <token> or &access_token=<token> query parameter.
    $ curl --header 'Authorization: Bearer 9Dkv2W...gzpz' '<odoo-base-url>/oauth/userinfo'
    
    {"email": false, "sub": "1", "name": "Administrator"}
    

    API authorized with client credentials tokens

    It's also possible to create APIs for server-to-server requests from the Client.
    # -*- coding: utf-8 -*-
    
    from odoo import http
    from odoo.addons.galicea_openid_connect.api import resource
    
    class ExternalAPI(http.Controller):
        @resource('/oauth/clientinfo', method='GET', auth='client')
        def clientinfo(self, req, **query):
            client = req.env['galicea_openid_connect.client'].browse(req.context['client_id'])
            return {
                'name': client.name
            }
    
    (note that this particular endpoint is bundled into galicea_openid_connect add-on as well). In order to receive the access token, the client needs to call the /oauth/token endpoint with &grant_type=client_credentials parameter:
    $ curl -X POST '<odoo-base-url>/oauth/token?grant_type=client_credentials&client_id=dr...ds&client_secret=DL...gO'
    
    {"access_token": "WWy74uJIIRA4bonJHdVUeY3N8Jn2vuMecIfQntLf5FvCj3C3nNJY9tRER0qcoHRw", "token_type": "bearer"}
    
    Such token can then be used to access the resource:
    $ curl --header 'Authorization: Bearer WWy...coHRw' '<odoo-base-url>/oauth/clientinfo'
    
    {"name": "Test Client"}
    

    Additional notes

    • In order to support OpenID Connect features related to authentication time, this also adds time of the user log-in to Odoo session.
    • For each client, a special kind of public user ("system user") is created to be impersonated during the server-server API requests.