OCA / odoorpc

Python module to pilot your Odoo servers through JSON-RPC.
http://pythonhosted.org/OdooRPC/
GNU Lesser General Public License v3.0
237 stars 125 forks source link

Does this library support authentication with oauth? #48

Closed javimurcia closed 5 years ago

javimurcia commented 5 years ago

As the title says, every examples uses the credentials from a local user in the instance. Would it be posible to authenticate via other means, like oauth?

sebalix commented 5 years ago

@crazy-projects I'm not an expert regarding OAuth, is the parameter opener of odoorpc.ODOO could do the job to integrate OAuth mechanism or there is extra work to do? https://odoorpc.readthedocs.io/en/latest/ref_odoo.html#odoorpc.ODOO

sebalix commented 5 years ago

I mean, if implementing an opener is enough to get OAuth support, we could provide it to ease its use (from odoorpc import OauthHandler for instance) but as said from now I don't know if it's enough. If you know the protocol feel free to contribute!

javimurcia commented 5 years ago

Maybe its not to the lib to support oauth. As i can see in odoo docs (quick scroll, less than 5 minutes) odoo authenticates api calls via http basic authentication. Is that correct? If that were the case, then it's imposible for the library to support oauth, since with ouauth the app (the library in this case) never sees the password. The flow is at follows.

  1. An external app (in this case oodo) wants to access protected information on another server. In our case, the only information odoo request is the basic account information (user id, email, password is never shared), so it can match the external user with a local user account.
  2. In order to do that, our odoo server redirects our user to a page specified by the oauth provider, and encodes certain information in the url parameters, such as the return url, and a nonce.
  3. The user arrives at the oauth provider (remember, our odoo instance redirected it) and is presented with a login prompt (controlled by the oauth provider, so we can't see the credentials). Aditionaly the oauth provider might show an aditional screen requesting confirmation from the user to allow access to the requested information (one of the parameter requested in the url is the "scope" or how much info do we want. We can request access to the user friends list for example).
  4. If the user logs in correctly and consents, the oauth provider send the user back to our odoo instance, (to the return url specified in the first redirect). To the return url, a extra parameter is added, a short lived token.
  5. Our user is back to our odoo, and odoo retrives from the url parameters that short token. Then odoo does in the background (withouth the user being aware, while the page loads)
    1. Reach to the oauth provider, and check the authenticity of the short lived token (after all, the user could type the return url, and forge a short lived token).
    2. If the shot lived token is valid, the oauth provider issues a bearer token, and optionaly a refresh token. The bearer token has a definite validity (the oauth provider announces its validity when issuing) and the refresh token last forever, or for a long time. When the bearer token, the app (in this case the odoo server) can use the refresh token to get a new bearer token. Mos of the time, this action invalidates the refresh token, so along the new bearer token, a new refresh token is used.
    3. When odoo wants to access protected resources, it send a request to the server, and includes the bearer token in the header as a method of authentication.

In our case, (this is a guess, since i haven't looked at the code or anything) I suppose odoo obtain the bearer token, and retrieves the account information from the oauth provider, and once matched with a local username, then the session is handled by odoo. However, oauth users are handled a little different from local users, since if you try to log to the same user in another browser, and both times you use oauth, the first session is logged out (there is a plugin to prevent that).

So closing up, i thing the question is more in the lines of how does odoo handle XMLRPC calls, specially its authentication, since if it only support http basic auth, then the only valid credentials are a local user and password. Can you shed more light into this?.

Thank you!.

El mié., 17 jul. 2019 13:56, Sébastien Alix notifications@github.com escribió:

@crazy-projects https://github.com/crazy-projects I'm not an expert regarding OAuth, is the parameter opener of odoorpc.ODOO could do the job to integrate OAuth mechanism or there is extra work to do? https://odoorpc.readthedocs.io/en/latest/ref_odoo.html#odoorpc.ODOO

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/OCA/odoorpc/issues/48?email_source=notifications&email_token=AH7K3QKSAR4JETO6UUCLRPTP74CGJA5CNFSM4IEOMAD2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2D6KRI#issuecomment-512222533, or mute the thread https://github.com/notifications/unsubscribe-auth/AH7K3QP7XLE73UQTOMCT4U3P74CGJANCNFSM4IEOMADQ .

sebalix commented 5 years ago

@crazy-projects thanks for the details. Regarding the authentication mechanism used by OdooRPC, it's a mix of two:

  1. Cookie to store the session, so the password is not required for further RPC calls (=> all HTTP controllers excepting /jsonrpc, it's like doing the same job than the Web client)
  2. "Basic Auth" if we can call it like that where the user/password is sent each time (/jsonrpc endpoint). The majority of requests are done this way.

I would like to support only 1. but I remember there was some issues to support some features (like reports), and 2. is the easy way and "official" interface (with XML-RPC).

About Odoo, I remember that on their SaaS (where OAuth is used I suppose), it was required to set a password on the user if we wanted to authenticate with XML-RPC (and JSON-RPC?). Don't know if it is still valid.

javimurcia commented 5 years ago
  1. Cookie to store the session, so the password is not required for further RPC calls (=> all HTTP controllers excepting /jsonrpc, it's like doing the same job than the Web client)
  2. "Basic Auth" if we can call it like that where the user/password is sent each time (/jsonrpc endpoint). The majority of requests are done this way.

Then the /jsonrpc ONLY supports basic auth? If that's the case then there is nothing to do (on this side). If it also allows cookie auth, then we might be able to create something.

By the way, you can call it basic auth (it's full name would be the basic http authentication scheme, it has it's own rfc) is the simplest authentication method available via http, you just concatenate the user and the password separated by a : base 64 encode it, and send it in every request in the Authorization header, in the form of Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

sebalix commented 5 years ago

No, the JSON-RPC and XML-RPC official interfaces (the one documented by Odoo documentation) do not use the HTTP Basic Authentication, that's why I put it between quotes :p It's a normal HTTP request sent to /jsonrpc endpoint: login and password are in the args parameters: https://github.com/odoo/odoo/blob/12.0/odoo/addons/base/controllers/rpc.py#L69 pass as params to dispatch_rpc: https://github.com/odoo/odoo/blob/8f4b98e67fe49516c0c830524de351db67c58357/odoo/http.py#L95 these params are then explode in the exp_authenticate method (common service) for the authentication process (returning the UID): https://github.com/odoo/odoo/blob/8f4b98e67fe49516c0c830524de351db67c58357/odoo/service/common.py#L21 and UID and password params are always sent for further requests (to read some data for instance): https://github.com/odoo/odoo/blob/8f4b98e67fe49516c0c830524de351db67c58357/odoo/service/model.py#L23

So to me it is not what we call HTTP Basic Auth.

But if you are using the JSON-RPC interface used by the Javascript web client (so HTTP controllers implemented by by the web module, while the /jsonrpc is implemented by base), then it's handled by a session stored in a cookie (the authentication is done through /web/session/authenticate https://github.com/odoo/odoo/blob/12.0/addons/web/controllers/main.py#L809), and further requests to /web/* do not need the user's password anymore.

In fact there is no Basic Auth at all in Odoo.

javimurcia commented 5 years ago

In fact there is no Basic Auth at all in Odoo.

It appears i missinterpreted this line auth_handler = urllib.request.HTTPBasicAuthHandler(pwd_mgr)

Anyway i'm closing this since there is no way to use this library without the user and pass of a local user account, so i'll start investigating the odoo side of the equation. Thank you for your time and patience.

sebalix commented 5 years ago

@crazy-projects yes it was an example of how to handle the Basic Auth with an URL opener if there is any in front of Odoo :)