Before this commit the neutralize system introduced in v16 was using ORM
methods in order to change appropriate records. Although flexible, this approach
could lead to call some methods with side effects while neutralizing
(eg: overloads of write).
This patch converts the neutralize system to a safer "inert" SQL based approach
by migrating the generic method _neutralize to SQL files exposed in the
data folder.
Task id: 2961687closesodoo/odoo#102792
X-original-commit: e5dbded9bb363351feff7ca8a56c7f8a6860f492
Related: odoo/enterprise#32580
Signed-off-by: Fabien Meghazi <fme@odoo.com>
In discussing 56fe16bd I was reminded to re-set the `user_id` from
`sub` in case an override / other client would be using it, but we
didn't think that an override might also be *setting* this work key,
which apparently is the case.
Therefore restore the old behavior of *getting* the user_id from the
response object, migration to using `sub` (and removal of compat with
`user_id` and `id`) will be done when the module is reworked and the
flow compatibility, nonce, etc... are all fixed.
closesodoo/odoo#91996
X-original-commit: a787a2f644e9e83dc6320eaf372e657718fd2e22
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
The current implementation is rather non-standard and largely an
ad-hoc pre-RFC implementation, with a number of incompatibilities with
the standard & actual real-world identity providers (IDP).
Tested with the following IDP:
- google oauth v1
- google oauth v3
- auth0
- okta
Add support to bearer Authorization
===================================
Sending the access token via "Authorization: Bearer $TOK" is strongly
recommended by the RFC, and required for all IDP to support. The query
parameter method is a legacy compatibility method and should be
avoided.
Query parameter access tokens are supported by Google (both v1 and
v3), and auth0, but not okta. All three support bearer tokens. However
making this the default is complicated by compatibility issues with
current behavior.
Use standard `sub`ject for identity
===================================
The specification defines `sub` as the userinfo key providing the user
identifier at the IDP.
- auth0, okta, and google v3 use `sub`
- google v1 uses `id`
- google v1's `tokeninfo` (possibly v3 as well, not tested) uses
`user_id`
- odoo replicates the google v1 tokeninfo behavior, using `user_id`
All the code is now standardised on `sub`, with `_auth_oauth_validate`
performing unification under that key.
Support non-json error bodies and WWW-Authenticate
==================================================
Per-spec, there is no requirement for error (userinfo) responses to
return any body, and all error information can be returned via
`WWW-Authenticate`.
Both auth0 and okta return empty bodies on error, though only okta
returns a useful www-authenticate, or relevant 40x statuses (auth0
seems to always return 400, okta has been observed to return both 400
and 401 depending on client error).
Error handling in `_auth_oauth_rpc` has been updated to only parse the
body as json on success (200), and fallback on a generic error payload
if `WWW-Authenticate` doesn't contain relevant information.
Nonce
=====
Okta requires a nonce to be provided.
Misc
====
A few improvements which are in no way required but should make things
simpler / clearer:
- update the default scope to match the standard for the implicit
flow's values (intersected with our requirements)
- update the default google configuration to use the v3 endpoints and
drop the tokeninfo request, remove the explicit scopes
- update the label of `validation_endpoint` to match the official
terminology, same with `auth_endpoint`
- add a label to `body` in order to explain what it's for (as that's
really confusing when the form just says `body` until you hover the
field)
Expected future updates
=======================
These issues were left out and may lead to degraded security, but were
considered too large changes fora stable compatibility-oriented
update:
* store and validate the nonce
* request and properly validate the id token, as well as validate the
access token (implicit guide sections 2.2.1, 2.2.2)
* implement "basic" flow[^basic], and / or "hybrid" flow, the implicit
flow[^implicit] is intended for purely client-side applications
(SPAs), the "authorization code" flow is intended as the primary
flow for normal web applications involving a server component,
the main advantage of the hybrid flow is that the id token *can*
contain the claims selected by `scope`, avoiding the need for the
userinfo request[^idtoken]
* remove support for query parameter requests
* remove support for Google's v1 oauth and subject identifiers other
than `sub`, facebook has not been tested but looks to support that
key as well in the OpenGraph API[^fb], this will require migrating
existing google providers to v3 implicitly (but would allow
simplifying their configuration)
References: RFC 6749, RFC 6750, Implicit Client Implementer's Guide
1.0 draft 23[^implicit]
Closes#88618, closes#64348, fixes#63963, closes#63970,
closes#69568
[^implicit]: https://openid.net/specs/openid-connect-implicit-1_0.html
[^basic]: https://openid.net/specs/openid-connect-basic-1_0.html also
known as "authorization code" flow
[^fb]: https://www.facebook.com/.well-known/openid-configuration
[^idtoken]: during testing, only auth0 returned the additional claims
as part of the id token, but this may be a configuration
issue
closesodoo/odoo#91262
X-original-commit: fb3c4845b1549bc2e1378620a5f01e52aa4dbbdb
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is the 12th commit of a comprehensive refactor of our HTTP
framework. See odoo/odoo#78857 for complete historic, discussions and
rationnals.
The web module is twofold, on one side there are many controllers: /,
/web, /web/login, /web/database/selector, /web/dataset/call_kw, etc, on
the other side there is `session_info`: the method responsible to create
the web client's environ.
This module is kinda an exception as it is (with base) a server wide
module. In the case of the HTTP framework, it means that the controllers
of web are always accessible, i.e. going to / or /web/login will never
return a 404 Not Found even if the user is not connected to a database.
This is both a blessing and a curse. It is a blessing because the
controllers are always accessible it means that a new users can freely
access those routes. It is a curse because *any* user can access them,
even user who don't have a session yet thus who are not connected to a
database yet. From a developer standpoint, we have to put extra care to
correct serve users with and without a database. An example is the
/web/login route, the login/password pair is stored in a database,
without database it is impossible to validate a user login but users can
still access this route without db.
To solve this problem, there is the `ensure_db` function. This function
attempts to find a database using various sources (?db= query-string,
session db, mono db) and to save it on the user session. In case no db
is found, the user is redirected to the database selector. In a way,
this function grants a database to the user in a seamingly experience.
In a way, this function brings a welcome differentiation between
`auth='none'` with a database and `auth='none'` without a database. Such
differentiation only matters for the server wide modules as "regular"
module controllers are only accessible via the ir.http routing map, i.e.
it is not possible to declare a nodb controller outside of server wide
modules.
An important changement is the `session.authenticate` method, before it
was possible to call the method when the cursor was not yet initialized,
authenticate would open a cursor against the given database, setup a
registry and an environment and ultimately save everything on the
current request. Because the cursor is now greedily created, it is no
more possible to update the request environment when authenticating on
another database.
PR: odoo#78857
Task: 2571224
Purpose
=======
Several actions are done even if nothing has changed on the configuration.
Example:
Writing on a cron the same value makes a dummy write-lock on the table
...
Part-of: odoo/odoo#82999
As an overridable _neutralize model method was added in a previous
commit, the method is now implemented for various models.
closesodoo/odoo#67825
Related: odoo/enterprise#19042
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Allows accessing various keys, especially whether this is an
interactive login or not.
Also have the xml-rpc `login` delegate to `authenticate` instead of
having its own half-assed implementation.
And remove some dead code: as far as I can tell, Session.authenticate
is never called with a uid.
A sequence field is present in the model but was not used.
After this commit, the field is used as sorting criteria. This allows to sort providers on the login page.
closesodoo/odoo#43968
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
If the record with the external id 'auth_oauth.provider_google' does
not exist in the database, 'google_provider' variable will contains
None.
Before this commit, calling get and set methods produced an error.
After this commit, trying to set a token for Google Authentication
will do nothing.
While this is not ideal, one can assume somebody that deleted an OAuth
provider rarely wants to configure it and can still upgrade the module
to get it back.
closesodoo/odoo#45566
X-original-commit: eca90a31d0d3667cf63994d34c5d2bb81bfd45c4
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Task 31122 section 4.
Implement per-IP rate limiting of login attempts after some number
of failures.
* check_credentials has no reason to be public, make it private
* add hooks to check for login cooldown on a source IP (remote_addr:
http://werkzeug.pocoo.org/docs/0.14/wrappers/#werkzeug.wrappers.BaseRequest.remote_addr)
basis
* add baseline/default configuration of 60s cooldown
* add baseline threshold of 10 login failures, after checking odoo.com
logs it looks like we have short runs of up to 7 failures (assumed
to be legitimate) before the user either gets it right or goes and
looks it up
Depends on #24187
Since 5425316eff errors when signing up will only display two
messages:
* "Another user is already registered using this email address." or
* "Could not create a new account."
While Odoo creates a multitude of other comprehensible error messages
such as
* "Passwords do not match; please retype them."
* "Signup token '%s' is no longer valid"
This commit now separate UserError and AssertionError from SignupErrors.
Those are still hidden in a general message (see 5425316eff for reasons) while
the other ones are fully displayed.
This commit also improves translations of messages.
Currently, all the methods that start with `get_default_` and `set_` are called on a res.config.settings loading or saving.
This commit purpose is to replace all the occurences of `get_default_foo` and `set_foo`. As these methods won't be called anymore, a warning is logged to notice its deprecation.
The generic method `get_default_fields` and `set_fields` could be improved too. The method names and API are not so good:
Why "default" fields? What you ask for is the current value of the stuff, shown as fields in the model. The values are fed as default values in the wizard, but that's an implementation trick.
Why "fields"? What you ask for are configuration parameters, and such things.
Why passing a list of fields? Its value is never used.
We should further simplify the API of both methods to something like
def get_values(self):
return {}
def set_values(self):
pass
In Python 3, all of these were "consolidated" under urllib(.request,
.parse, .errors) which is inconvenient.
Since we already have hard dependencies on requests and
werkzeug(.urls, which is a backport of Python 3's unicode-aware
urllib.parse) migrate *everything* to that.
A sticking point is urllib2.URLError, those were (mostly) replaced by
the slightly more general IOError which URLError extends.