You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
6.8 KiB

  1. <section class="oe_container">
  2. <div class="oe_row oe_spaced">
  3. <div class="oe_span12">
  4. <h2 class="oe_slogan">Galicea OpenID Connect Provider</h2>
  5. <h3 class="oe_slogan">
  6. OpenID Connect Provider for Odoo &amp; OAuth2 resource server
  7. </h3>
  8. <p>
  9. 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. <i>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 <tt>openid</tt>) and no permission is required from the user to share their identity with the client.</i></p>
  10. <p>The add-on also provides OAuth2 token validation for use in custom API endpoints. This allows the clients to securely fetch data from Odoo.</p>
  11. <h2>Prerequisites</h2>
  12. <pre>
  13. pip install -r galicea_openid_connect/requirements.txt
  14. </pre>
  15. <h2>Client configuration</h2>
  16. <p>
  17. Simply go to <tt>OpenID Connect Provider</tt> menu to register a new client. Make sure that the <tt>Redirect URI</tt> exactly matches <tt>redirect_uri</tt> parameter your client is going to send. Copy generated <tt>Client ID</tt> and <tt>Client secret</tt> to configure your client.
  18. </p>
  19. <p>
  20. You can use <a href="https://openid.net/specs/openid-connect-discovery-1_0.html">OpenID Connect Discovery</a> to set up your client. The discovery document URL will be located at <tt>&lt;odoo-base-url&gt;/.well-known/openid-configuration</tt> and it looks like this: <pre>
  21. {
  22. "authorization_endpoint": "&lt;odoo-base-url&gt;/oauth/authorize",
  23. "grant_types_supported": [
  24. "authorization_code",
  25. "implicit"
  26. ],
  27. "id_token_signing_alg_values_supported": [
  28. "RS256"
  29. ],
  30. "issuer": "&lt;odoo-base-url&gt;/",
  31. "jwks_uri": "&lt;odoo-base-url&gt;/oauth/jwks",
  32. "response_types_supported": [
  33. "code",
  34. "token",
  35. "id_token token",
  36. "id_token"
  37. ],
  38. "scopes_supported": [
  39. "openid"
  40. ],
  41. "subject_types_supported": [
  42. "public"
  43. ],
  44. "token_endpoint": "&lt;odoo-base-url&gt;/oauth/token",
  45. "token_endpoint_auth_methods_supported": [
  46. "client_secret_post"
  47. ],
  48. "userinfo_endpoint": "&lt;odoo-base-url&gt;/oauth/userinfo"
  49. }
  50. </pre>
  51. <h3>Configuring other Odoo instance/DB to be the client</h3>
  52. <p>Let's say that you want to allow users registered in your <tt>master.odoo.com</tt> Odoo instance to be able to log into <tt>client.odoo.com</tt> instance, without having to create a separate account.</p>
  53. <p>To do that, simply install this module on <tt>master.odoo.com</tt> and add the client, using <tt>/auth_oauth/signin</tt> as a redirect_uri:</p>
  54. <img class="oe_picture oe_screenshot" src="images/master_screenshot.png" />
  55. <p>Now, in <tt>client.odoo.com</tt>:
  56. <ul>
  57. <li>install the <tt>auth_oauth</tt> add-on,</li>
  58. <li>enable developer mode,</li>
  59. <li>make sure that <tt>Allow external users to sign up</tt> option is enabled in <tt>General settings</tt></li>
  60. <li>add the following OAuth Provider data in the settings:</li>
  61. <img class="oe_picture oe_screenshot" src="images/client_screenshot.png" />
  62. </p>
  63. Now, the users of <tt>client.odoo.com</tt> will be able to login using new <tt>Login with Master</tt> link.
  64. <img class="oe_picture oe_screenshot" src="images/login_screenshot.png" />
  65. In case they are already logged into <tt>master.odoo.com</tt>, all they need to do is to click it. Otherwise, they will be redirected to <tt>master.odoo.com</tt> to provide their credentials.
  66. <div class="alert alert-danger" role="alert">
  67. <b>Warning!</b> The user of <tt>master.odoo.com</tt> will not be able to log into <tt>client.odoo.com</tt> if there already is a regular account with the same e-mail address in <tt>client.odoo.com</tt>. In that case you will see this message:
  68. <img class="oe_picture oe_screenshot" src="images/error_screenshot.png" />
  69. </div>
  70. <h2>Creating JSON APIs with OAuth2 authorization</h2>
  71. <p>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.</p>
  72. <p>You can create such API in a way that is similar to creating regular Odoo controllers:</p>
  73. <pre>
  74. # -*- coding: utf-8 -*-
  75. from odoo import http
  76. from odoo.addons.galicea_openid_connect.api import resource
  77. class ExternalAPI(http.Controller):
  78. @resource('/oauth/userinfo', method='GET')
  79. def userinfo(self, req, **query):
  80. user = req.env.user
  81. return {
  82. 'sub': str(user.id),
  83. 'name': user.name,
  84. 'email': user.email
  85. }
  86. </pre>
  87. (note that this particular endpoint is bundled into <tt>galicea_openid_connect</tt> add-on). The client can then call this endpoint with either a header that looks like <tt>Authorization: Bearer &lt;token&gt;</tt> or <tt>&amp;access_token=&lt;token&gt;</tt> query parameter.
  88. <pre>
  89. $ curl --header 'Authorization: Bearer 9Dkv2W...gzpz' '&lt;odoo-base-url&gt;/oauth/userinfo'
  90. {"email": false, "sub": "1", "name": "Administrator"}
  91. </pre>
  92. <h3>API authorized with client credentials tokens</h3>
  93. It's also possible to create APIs for server-to-server requests from the Client.
  94. <pre>
  95. # -*- coding: utf-8 -*-
  96. from odoo import http
  97. from odoo.addons.galicea_openid_connect.api import resource
  98. class ExternalAPI(http.Controller):
  99. @resource('/oauth/clientinfo', method='GET'<b>, auth='client'</b>)
  100. def clientinfo(self, req, **query):
  101. client = req.env['galicea_openid_connect.client'].browse(req.context['client_id'])
  102. return {
  103. 'name': client.name
  104. }
  105. </pre>
  106. (note that this particular endpoint is bundled into <tt>galicea_openid_connect</tt> add-on as well). In order to receive the access token, the client needs to call the <tt>/oauth/token</tt> endpoint with <tt>&amp;grant_type=client_credentials</tt> parameter:
  107. <pre>
  108. $ curl -X POST '&lt;odoo-base-url&gt;/oauth/token?grant_type=client_credentials&client_id=dr...ds&client_secret=DL...gO'
  109. {"access_token": "WWy74uJIIRA4bonJHdVUeY3N8Jn2vuMecIfQntLf5FvCj3C3nNJY9tRER0qcoHRw", "token_type": "bearer"}
  110. </pre>
  111. Such token can then be used to access the resource:
  112. <pre>
  113. $ curl --header 'Authorization: Bearer WWy...coHRw' '&lt;odoo-base-url&gt;/oauth/clientinfo'
  114. {"name": "Test Client"}
  115. </pre>
  116. <h2>Additional notes</h2>
  117. <ul>
  118. <li>In order to support OpenID Connect features related to authentication time, this also adds time of the user log-in to Odoo session.</li>
  119. <li>For each client, a special kind of public user ("system user") is created to be impersonated during the server-server API requests.</li>
  120. </ul>
  121. </div>
  122. </div>
  123. </section>