Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
ADD "API keys" for password-less RPC access #33637
Pre-requisite for 2FA / TOTP.
Actual API keys implementation is the third commit, the other two are improvements to make things possible or better:
Also improve Users.check to match Users.authenticate: no need to bother with auth process if the current user is not active. And remove some dead code: as far as I can tell, Session.authenticate is never called with a uid.
Before this, invalidations to the UID cache is not synchronised between workers because it's an ad-hoc solution (so a user changing their password or an admin disabling a user would only lock out an attacker currently using the API of one of possibly several workers). Shift the entire thing to ormcache which already has proper support for synchronising cache invalidation between workers. Also simplify the cache invalidation mess in Users.write because the caches have been unified into a single registry-level LRU, so the half-dozen cache clears on specific ormcached methods & models is pretty much the same as repeatedly calling clear_caches on the current model. **However** registry.cache is trivially accessible from server actions and safe_eval as long as they provide access to a model (through `model.pool.cache`). Which is common, and an issue given we're very much putting sensible data in there. Fix this by renaming `Registry.cache` to `Registry.__cache`, this requires few editions and mangled names are not accessible from safe_eval contexts. The alternative would have been to add more bespoke handling of the uid cache to hook it into the cache invalidation propagation machinery. After discussion with @odony, fixing LRU access and using that seems cleaner and less error-prone. Note on lazy_property ===================== Make Registry.cache / Registry.__cache into a regular attribute: the overhead of the LRU is not that high (compared to that of the registry itself), it's rare that we *don't* need it, and it's assumed to be a persisted attribute (it's not just a cache) so making it a normal attribute seems fine; and lazy_property doesn't work for mangled names: the name of the property is mangled using the name of the definition class, but the name of the symbol (fget) is not mangled so lazy_property would set the __cache attribute but then Python would lookup _Registry__cache, creating a new cache every access. And we can't (always) mangle things correctly on `__get__(obj, owner)`: `owner` is just `type(obj)`, meaning in the case of inheritance the type we get is the type through which the property is accessed rather than the one it's defined on. So it would work in the cases where no inheritance is involved (such as Registry.__cache) but not in general (lest we want to play around walking the MRO ourselves to find the definition source, which doesn't seem worth it). lazy_property *could* be made to work properly on Python 3.6+: the descriptor protocol gains `__set_name__(name, owner)`, which is called with the properly mangled name — and with the definition class to boot (though there might still be issues when overriding lazy properties as the override will be mangled & named differently... or maybe that's a feature?). However we're still supporting 3.5 at this point, AFAIK, so that's not an option. Plus it feels unnecessary / not very useful. However add an assertion to `lazy_property` so it signals when we try to use it on a mangled method (as otherwise it kinda sorta work in the sense that the property / object is accessible but is in effect a slower way to write a regular property).
* ability for a user to request / create keys associated to their user * can require authentication solely though API keys, use a computed field so it can be overridden (to require API auth even in situations where the user has not requested it themselves) * hash keys just in case as we can do so and might as well, add a cleartext index (first 4 bytes of 20) to avoid blowing up the DB if a user decides to create millions of keys for some daft reason * users can delete their own keys, admins can delete (invalidate) anyone's keys
* migrate website to overriding web_login less (still needed to flag it as website-enabled) and use _login_redirect for its login redirection override needs * modify portal and website to not replace / shortcut the redirection workflow, so it's possible to override those properly if / as necessary
The actual secret is never stored in cleartext, hashed and that hash isn't even visible to Odoo by default (there's no field for it). The only thing hiding the record would do is preclude auditing and deleting existing keys.
Delete the key.