middleware.rst 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. .. _using_middleware:
  2. Using :mod:`repoze.who` Middleware
  3. ==================================
  4. .. _middleware_responsibilities:
  5. Middleware Responsibilities
  6. ---------------------------
  7. :mod:`repoze.who` as middleware has one major function on ingress: it
  8. conditionally places identification and authentication information
  9. (including a ``REMOTE_USER`` value) into the WSGI environment and
  10. allows the request to continue to a downstream WSGI application.
  11. :mod:`repoze.who` as middleware has one major function on egress: it
  12. examines the headers set by the downstream application, the WSGI
  13. environment, or headers supplied by other plugins and conditionally
  14. challenges for credentials.
  15. .. _request_lifecycle:
  16. Lifecycle of a Request
  17. ----------------------
  18. :mod:`repoze.who` performs duties both on middleware "ingress" and on
  19. middleware "egress". The following graphic outlines where it sits in the context
  20. of the request and its response:
  21. .. image:: .static/request-lifecycle.png
  22. .. _ingress_stages:
  23. Request (Ingress) Stages
  24. ++++++++++++++++++++++++
  25. .. image:: .static/ingress.png
  26. :mod:`repoze.who` performs the following operations in the following
  27. order during middleware ingress:
  28. #. Environment Setup
  29. The middleware adds a number of keys to the WSGI environment:
  30. ``repoze.who.plugins``
  31. A reference to the configured plugin set.
  32. ``repoze.who.logger``
  33. A reference to the logger configured into the middleware.
  34. ``repoze.who.application``
  35. A refererence to the "right-hand" application. The plugins
  36. consulted during request classification / identification /
  37. authentication may replace this application with another
  38. WSGI application, which will be used for the remainer of the
  39. current request.
  40. #. Request Classification
  41. The middleware hands the WSGI environment to the configured ``classifier``
  42. plugin, which is responsible for classifying the request into a single
  43. "type". This plugin must return a single string value classifying the
  44. request, e.g., "browser", "xml-rpc", "webdav", etc.
  45. This classification may serve to filter out plugins consulted later in
  46. the request. For instance, a plugin which issued a challenge as an
  47. HTML form would be inappropriate for use in requests from an XML-RPC
  48. or WebDAV client.
  49. #. Identification
  50. Each plugin configured as an identifier for a particular class of
  51. request is called to extract identity data ("credentials") from the
  52. WSGI environment.
  53. For example, a basic auth identifier might use
  54. the ``HTTP_AUTHORIZATION`` header to find login and password
  55. information. Each configured identifier plugin is consulted in turn,
  56. and any non-None identities returned are collected into a list to be
  57. authenticated.
  58. Identifiers are also responsible for providing header information used
  59. to set and remove authentication information in the response during
  60. egress (to "remember" or "forget" the currently-authenticated user).
  61. #. Authentication
  62. The middlware consults each plugin configured as an authenticators for
  63. a particular class of request, to compare credentials extracted by the
  64. identification plugins to a given policy, or set of valid credentials.
  65. For example, an htpasswd authenticator might look in a file for a user
  66. record matching any of the extracted credentials. If it finds one, and
  67. if the password listed in the record matches the password in the
  68. identity, the userid of the user would be returned (which would
  69. be the same as the login name). Successfully-authenticated ndenties are
  70. "weighted", with the highest weight identity governing the remainder of
  71. the request.
  72. #. Metadata Assignment
  73. After identifying and authenticating a user, :mod:`repoze.who` consults
  74. plugins configured as metadata providers, which may augmented the
  75. authenticated identity with arbitrary metadata.
  76. For example, a metadata provider plugin might add the user's first,
  77. middle and last names to the identity. A more specialized metadata
  78. provider might augment the identity with a list of role or group names
  79. assigned to the user.
  80. .. _egress_stages:
  81. Response (Egress) Stages
  82. ++++++++++++++++++++++++
  83. :mod:`repoze.who` performs the following operations in the following
  84. order during middleware egress:
  85. #. Challenge Decision
  86. The middleare examines the WSGI environment and the status and headers
  87. returned by the downstream application to determine whether a
  88. challenge is required. Typically, only the status is used: if it
  89. starts with ``401``, a challenge is required, and the challenge
  90. decider returns True.
  91. This behavior can be replaced by configuring a different
  92. ``challenge_decider`` plugin for the middleware.
  93. If a challenge is required, the challenge decider returns True; otherwise,
  94. it returns False.
  95. #. Credentials reset, AKA "forgetting"
  96. If the challenge decider returns True, the middleware first delegates
  97. to the identifier plugin which provided the currently-authenticated
  98. identity to "forget" the identity, by adding response headers (e.g., to
  99. expire a cookie).
  100. #. Challenge
  101. The plugin then consults each of the set of plugins configured as
  102. challengers for the current request classification: the first plugin
  103. which returns a non-None WSGI application will be used perform a
  104. challenge.
  105. Challenger plugins may use application-returned headers, the WSGI
  106. environment, and other items to determine what sort of operation
  107. should be performed to actuate the challenge.
  108. #. Remember
  109. The identifier plugin that the "best" set of credentials came from
  110. (if any) will be consulted to "remember" these credentials if the
  111. challenge decider returns False.