auth.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. # Copyright 2019 The Matrix.org Foundation C.I.C.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import logging
  15. from typing import TYPE_CHECKING, Optional
  16. from twisted.web.server import Request
  17. from sydent.db.accounts import AccountStore
  18. from sydent.http.servlets import MatrixRestError, get_args
  19. from sydent.terms.terms import get_terms
  20. if TYPE_CHECKING:
  21. from sydent.db.accounts import Account
  22. from sydent.sydent import Sydent
  23. logger = logging.getLogger(__name__)
  24. def tokenFromRequest(request: "Request") -> Optional[str]:
  25. """Extract token from header of query parameter.
  26. :param request: The request to look for an access token in.
  27. :return: The token or None if not found
  28. """
  29. token = None
  30. # check for Authorization header first
  31. authHeader = request.getHeader("Authorization")
  32. if authHeader is not None and authHeader.startswith("Bearer "):
  33. token = authHeader[len("Bearer ") :]
  34. # no? try access_token query param
  35. if token is None:
  36. args = get_args(request, ("access_token",), required=False)
  37. token = args.get("access_token")
  38. # Ensure we're dealing with unicode.
  39. if token and isinstance(token, bytes):
  40. token = token.decode("UTF-8")
  41. return token
  42. def authV2(
  43. sydent: "Sydent",
  44. request: "Request",
  45. requireTermsAgreed: bool = True,
  46. ) -> "Account":
  47. """For v2 APIs check that the request has a valid access token associated with it
  48. :param sydent: The Sydent instance to use.
  49. :param request: The request to look for an access token in.
  50. :param requireTermsAgreed: Whether to deny authentication if the user hasn't accepted
  51. the terms of service.
  52. :returns Account: The account object if there is correct auth
  53. :raises MatrixRestError: If the request is v2 but could not be authed or the user has
  54. not accepted terms.
  55. """
  56. token = tokenFromRequest(request)
  57. if token is None:
  58. raise MatrixRestError(401, "M_UNAUTHORIZED", "Unauthorized")
  59. accountStore = AccountStore(sydent)
  60. account = accountStore.getAccountByToken(token)
  61. if account is None:
  62. raise MatrixRestError(401, "M_UNAUTHORIZED", "Unauthorized")
  63. if requireTermsAgreed:
  64. terms = get_terms(sydent)
  65. if (
  66. terms.getMasterVersion() is not None
  67. and account.consentVersion != terms.getMasterVersion()
  68. ):
  69. raise MatrixRestError(403, "M_TERMS_NOT_SIGNED", "Terms not signed")
  70. return account