oauth2.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. # This file is part of Radicale Server - Calendar Server
  2. #
  3. # Original from https://gitlab.mim-libre.fr/alphabet/radicale_oauth/
  4. # Copyright © 2021-2022 Bruno Boiget
  5. # Copyright © 2022-2022 Daniel Dehennin
  6. #
  7. # Since migration into upstream
  8. # Copyright © 2025-2025 Peter Bieringer <pb@bieringer.de>
  9. #
  10. # This library is free software: you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License as published by
  12. # the Free Software Foundation, either version 3 of the License, or
  13. # (at your option) any later version.
  14. #
  15. # This library is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License
  21. # along with Radicale. If not, see <http://www.gnu.org/licenses/>.
  22. """
  23. Authentication backend that checks credentials against an oauth2 server auth endpoint
  24. """
  25. from radicale import auth
  26. from radicale.log import logger
  27. import requests
  28. from requests.utils import quote
  29. class Auth(auth.BaseAuth):
  30. def __init__(self, configuration):
  31. super().__init__(configuration)
  32. self._endpoint = configuration.get("auth", "oauth2_token_endpoint")
  33. logger.warning("Using oauth2 token endpoint: %s" % (self._endpoint))
  34. def login(self, login, password):
  35. """Validate credentials.
  36. Sends login credentials to oauth auth endpoint and checks that a token is returned
  37. """
  38. try:
  39. # authenticate to authentication endpoint and return login if ok, else ""
  40. req_params = {
  41. "username": login,
  42. "password": password,
  43. "grant_type": "password",
  44. "client_id": "radicale",
  45. }
  46. req_headers = {"Content-Type": "application/x-www-form-urlencoded"}
  47. response = requests.post(
  48. self._endpoint, data=req_params, headers=req_headers
  49. )
  50. if (
  51. response.status_code == requests.codes.ok
  52. and "access_token" in response.json()
  53. ):
  54. return login
  55. except OSError as e:
  56. raise RuntimeError(
  57. "Failed to authenticate against oauth server %r: %s"
  58. % (self._endpoint, e)
  59. ) from e
  60. logger.warning("User %s failed to authenticate" % (str(login)))
  61. return ""