From 5cf18393fbe9084e4b079a1136ed5de46ad89969 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Tue, 12 Aug 2014 20:49:11 -0500 Subject: Docs: Introduce the concept of "userid" into the glossary. --- docs/glossary.rst | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/glossary.rst b/docs/glossary.rst index deb4c1c8b..eb57f3d0d 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -286,13 +286,23 @@ Glossary :term:`authorization policy`. principal - A *principal* is a string or unicode object representing a userid - or a group id. It is provided by an :term:`authentication - policy`. For example, if a user had the user id "bob", and Bob - was part of two groups named "group foo" and "group bar", the - request might have information attached to it that would - indicate that Bob was represented by three principals: "bob", - "group foo" and "group bar". + A *principal* is a string or unicode object representing an + entity, typically a user or group, having zero or more + :term:`permissions `. Principals are provided by an + :term:`authentication policy`. For example, if a user had the + user id "bob", and Bob was part of two groups named "group foo" + and "group bar", the request might have information attached to + it that would indicate that Bob was represented by three + principals: "bob", "group foo" and "group bar". + + userid + A *userid* is a a string or unicode object used to identify and + authenticate a real-world user, often a person. A userid is + supplied to an :term:`authentication policy` in order to discover + the user's :term:`principals `. The default behavior + of the authentication policies :app:`Pyramid` provides is to + return the user's userid as one of the user's principals, but a + userid need not be a principal. authorization policy An authorization policy in :app:`Pyramid` terms is a bit of -- cgit v1.2.3 From 81719b800cfea1c6fd68427ea1d9c0a2f3e6c1dd Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Tue, 12 Aug 2014 21:56:26 -0500 Subject: Docs: Make clear that a userid need not be a principal. --- docs/api/request.rst | 10 ++++++---- docs/narr/security.rst | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/api/request.rst b/docs/api/request.rst index 77d80f6d6..3a32fd938 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -194,10 +194,12 @@ .. versionadded:: 1.5 A property which returns the list of 'effective' :term:`principal` - identifiers for this request. This will include the userid of the - currently authenticated user if a user is currently authenticated. If no - :term:`authentication policy` is in effect, this will return a sequence - containing only the :attr:`pyramid.security.Everyone` principal. + identifiers for this request. This list typically includes the + :term:`userid` of the currently authenticated user if a user is + currently authenticated, but this depends on the + :term:`authentication policy` in effect. If no :term:`authentication + policy` is in effect, this will return a sequence containing only the + :attr:`pyramid.security.Everyone` principal. .. method:: invoke_subrequest(request, use_tweens=False) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 8db23a33b..57d7ac38f 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -611,9 +611,9 @@ that implements the following interface: def effective_principals(self, request): """ Return a sequence representing the effective principals - including the userid and any groups belonged to by the current - user, including 'system' groups such as - ``pyramid.security.Everyone`` and + typically including the userid and any groups belonged to + by the current user, always including 'system' groups such + as ``pyramid.security.Everyone`` and ``pyramid.security.Authenticated``. """ def remember(self, request, principal, **kw): -- cgit v1.2.3 From c7afe4e43ab19a5e8274988fe8dd004c04c160a1 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Tue, 12 Aug 2014 22:10:03 -0500 Subject: Security: Change "principal" argument in security.remember() to "userid". Make the change througout the authentication policies, etc. as well. --- docs/narr/security.rst | 14 +++++++------- pyramid/authentication.py | 24 ++++++++++++------------ pyramid/interfaces.py | 4 ++-- pyramid/security.py | 6 +++--- pyramid/testing.py | 4 ++-- pyramid/tests/test_security.py | 4 ++-- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 57d7ac38f..16718cfa4 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -104,9 +104,9 @@ For example: The above configuration enables a policy which compares the value of an "auth ticket" cookie passed in the request's environment which contains a reference -to a single :term:`principal` against the principals present in any -:term:`ACL` found in the resource tree when attempting to call some -:term:`view`. +to a single :term:`userid` and matches that userid's principals against the +principals present in any :term:`ACL` found in the resource tree when +attempting to call some :term:`view`. While it is possible to mix and match different authentication and authorization policies, it is an error to configure a Pyramid application @@ -616,11 +616,11 @@ that implements the following interface: as ``pyramid.security.Everyone`` and ``pyramid.security.Authenticated``. """ - def remember(self, request, principal, **kw): + def remember(self, request, userid, **kw): """ Return a set of headers suitable for 'remembering' the - principal named ``principal`` when set in a response. An - individual authentication policy and its consumers can decide - on the composition and meaning of **kw. """ + userid named ``userid`` when set in a response. An + individual authentication policy and its consumers can + decide on the composition and meaning of **kw. """ def forget(self, request): """ Return a set of headers suitable for 'forgetting' the diff --git a/pyramid/authentication.py b/pyramid/authentication.py index b84981bbc..f4c211ffa 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -335,11 +335,11 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): effective_principals.extend(groups) return effective_principals - def remember(self, request, principal, **kw): - """ Store the ``principal`` as ``repoze.who.userid``. + def remember(self, request, userid, **kw): + """ Store the ``userid`` as ``repoze.who.userid``. The identity to authenticated to :mod:`repoze.who` - will contain the given principal as ``userid``, and + will contain the given userid as ``userid``, and provide all keyword arguments as additional identity keys. Useful keys could be ``max_age`` or ``userdata``. """ @@ -348,7 +348,7 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy): return [] environ = request.environ identity = kw - identity['repoze.who.userid'] = principal + identity['repoze.who.userid'] = userid return identifier.remember(environ, identity) def forget(self, request): @@ -404,7 +404,7 @@ class RemoteUserAuthenticationPolicy(CallbackAuthenticationPolicy): """ The ``REMOTE_USER`` value found within the ``environ``.""" return request.environ.get(self.environ_key) - def remember(self, request, principal, **kw): + def remember(self, request, userid, **kw): """ A no-op. The ``REMOTE_USER`` does not provide a protocol for remembering the user. This will be application-specific and can be done somewhere else or in a subclass.""" @@ -652,7 +652,7 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): if result: return result['userid'] - def remember(self, request, principal, **kw): + def remember(self, request, userid, **kw): """ Accepts the following kw args: ``max_age=, ``tokens=``. @@ -660,7 +660,7 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): the response. """ - return self.cookie.remember(request, principal, **kw) + return self.cookie.remember(request, userid, **kw) def forget(self, request): """ A list of headers which will delete appropriate cookies.""" @@ -1061,13 +1061,13 @@ class SessionAuthenticationPolicy(CallbackAuthenticationPolicy): self.userid_key = prefix + 'userid' self.debug = debug - def remember(self, request, principal, **kw): - """ Store a principal in the session.""" - request.session[self.userid_key] = principal + def remember(self, request, userid, **kw): + """ Store a userid in the session.""" + request.session[self.userid_key] = userid return [] def forget(self, request): - """ Remove the stored principal from the session.""" + """ Remove the stored userid from the session.""" if self.userid_key in request.session: del request.session[self.userid_key] return [] @@ -1132,7 +1132,7 @@ class BasicAuthAuthenticationPolicy(CallbackAuthenticationPolicy): if credentials: return credentials[0] - def remember(self, request, principal, **kw): + def remember(self, request, userid, **kw): """ A no-op. Basic authentication does not provide a protocol for remembering the user. Credentials are sent on every request. diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index c5a70dbfd..bba818c8a 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -460,9 +460,9 @@ class IAuthenticationPolicy(Interface): user, including 'system' groups such as Everyone and Authenticated. """ - def remember(request, principal, **kw): + def remember(request, userid, **kw): """ Return a set of headers suitable for 'remembering' the - principal named ``principal`` when set in a response. An + userid named ``userid`` when set in a response. An individual authentication policy and its consumers can decide on the composition and meaning of ``**kw.`` """ diff --git a/pyramid/security.py b/pyramid/security.py index 041155563..3cef7ee5a 100644 --- a/pyramid/security.py +++ b/pyramid/security.py @@ -115,12 +115,12 @@ deprecated( '"effective_principals" attribute of the Pyramid request instead.' ) -def remember(request, principal, **kw): +def remember(request, userid, **kw): """ Returns a sequence of header tuples (e.g. ``[('Set-Cookie', 'foo=abc')]``) on this request's response. These headers are suitable for 'remembering' a set of credentials - implied by the data passed as ``principal`` and ``*kw`` using the + implied by the data passed as ``userid`` and ``*kw`` using the current :term:`authentication policy`. Common usage might look like so within the body of a view function (``response`` is assumed to be a :term:`WebOb` -style :term:`response` object @@ -142,7 +142,7 @@ def remember(request, principal, **kw): policy = _get_authentication_policy(request) if policy is None: return [] - return policy.remember(request, principal, **kw) + return policy.remember(request, userid, **kw) def forget(request): """ diff --git a/pyramid/testing.py b/pyramid/testing.py index 8cbd8b82b..f77889e72 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -79,8 +79,8 @@ class DummySecurityPolicy(object): effective_principals.extend(self.groupids) return effective_principals - def remember(self, request, principal, **kw): - self.remembered = principal + def remember(self, request, userid, **kw): + self.remembered = userid return self.remember_result def forget(self, request): diff --git a/pyramid/tests/test_security.py b/pyramid/tests/test_security.py index 6f08a100c..027f9cda0 100644 --- a/pyramid/tests/test_security.py +++ b/pyramid/tests/test_security.py @@ -462,8 +462,8 @@ class DummyAuthenticationPolicy: def authenticated_userid(self, request): return self.result - def remember(self, request, principal, **kw): - headers = [(_TEST_HEADER, principal)] + def remember(self, request, userid, **kw): + headers = [(_TEST_HEADER, userid)] self._header_remembered = headers[0] return headers -- cgit v1.2.3 From dc324784193a577bc039dcddb0651ef5ec9e6f57 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Tue, 12 Aug 2014 22:12:25 -0500 Subject: Docs: Make "userid" link to the glossary term. --- docs/api/request.rst | 31 ++++++++++++++++--------------- docs/narr/security.rst | 24 +++++++++++++----------- docs/tutorials/wiki/design.rst | 4 ++-- docs/tutorials/wiki2/design.rst | 3 ++- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/docs/api/request.rst b/docs/api/request.rst index 3a32fd938..4f93fa34f 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -167,27 +167,28 @@ .. versionadded:: 1.5 - A property which returns the userid of the currently authenticated user - or ``None`` if there is no :term:`authentication policy` in effect or - there is no currently authenticated user. This differs from - :attr:`~pyramid.request.Request.unauthenticated_userid`, because the - effective authentication policy will have ensured that a record - associated with the userid exists in persistent storage; if it has - not, this value will be ``None``. + A property which returns the :term:`userid` of the currently + authenticated user or ``None`` if there is no :term:`authentication + policy` in effect or there is no currently authenticated user. This + differs from :attr:`~pyramid.request.Request.unauthenticated_userid`, + because the effective authentication policy will have ensured that a + record associated with the :term:`userid` exists in persistent storage; if it + has not, this value will be ``None``. .. attribute:: unauthenticated_userid .. versionadded:: 1.5 A property which returns a value which represents the *claimed* (not - verified) user id of the credentials present in the request. ``None`` if - there is no :term:`authentication policy` in effect or there is no user - data associated with the current request. This differs from - :attr:`~pyramid.request.Request.authenticated_userid`, because the - effective authentication policy will not ensure that a record associated - with the userid exists in persistent storage. Even if the userid - does not exist in persistent storage, this value will be the value - of the userid *claimed* by the request data. + verified) :term:`userid` of the credentials present in the + request. ``None`` if there is no :term:`authentication policy` in effect + or there is no user data associated with the current request. This + differs from :attr:`~pyramid.request.Request.authenticated_userid`, + because the effective authentication policy will not ensure that a + record associated with the :term:`userid` exists in persistent storage. + Even if the :term:`userid` does not exist in persistent storage, this + value will be the value of the :term:`userid` *claimed* by the request + data. .. attribute:: effective_principals diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 16718cfa4..f3879d0ba 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -595,19 +595,21 @@ that implements the following interface: """ An object representing a Pyramid authentication policy. """ def authenticated_userid(self, request): - """ Return the authenticated userid or ``None`` if no - authenticated userid can be found. This method of the policy - should ensure that a record exists in whatever persistent store is - used related to the user (the user should not have been deleted); - if a record associated with the current id does not exist in a - persistent store, it should return ``None``.""" + """ Return the authenticated :term:`userid` or ``None`` if + no authenticated userid can be found. This method of the + policy should ensure that a record exists in whatever + persistent store is used related to the user (the user + should not have been deleted); if a record associated with + the current id does not exist in a persistent store, it + should return ``None``.""" def unauthenticated_userid(self, request): - """ Return the *unauthenticated* userid. This method performs the - same duty as ``authenticated_userid`` but is permitted to return the - userid based only on data present in the request; it needn't (and - shouldn't) check any persistent store to ensure that the user record - related to the request userid exists.""" + """ Return the *unauthenticated* userid. This method + performs the same duty as ``authenticated_userid`` but is + permitted to return the userid based only on data present + in the request; it needn't (and shouldn't) check any + persistent store to ensure that the user record related to + the request userid exists.""" def effective_principals(self, request): """ Return a sequence representing the effective principals diff --git a/docs/tutorials/wiki/design.rst b/docs/tutorials/wiki/design.rst index eb785dd1c..28380bd66 100644 --- a/docs/tutorials/wiki/design.rst +++ b/docs/tutorials/wiki/design.rst @@ -53,10 +53,10 @@ Security We'll eventually be adding security to our application. The components we'll use to do this are below. -- USERS, a dictionary mapping usernames to their +- USERS, a dictionary mapping :term:`userids ` to their corresponding passwords. -- GROUPS, a dictionary mapping usernames to a +- GROUPS, a dictionary mapping :term:`userids ` to a list of groups to which they belong to. - ``groupfinder``, an *authorization callback* that looks up diff --git a/docs/tutorials/wiki2/design.rst b/docs/tutorials/wiki2/design.rst index df2c83398..ff7413668 100644 --- a/docs/tutorials/wiki2/design.rst +++ b/docs/tutorials/wiki2/design.rst @@ -53,7 +53,8 @@ Security We'll eventually be adding security to our application. The components we'll use to do this are below. -- USERS, a dictionary mapping users names to their corresponding passwords. +- USERS, a dictionary mapping users names (the user's :term:`userids + `) to their corresponding passwords. - GROUPS, a dictionary mapping user names to a list of groups they belong to. -- cgit v1.2.3 From a0cba72fb9925a1476ebf0848fa6ae07bbea5840 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Tue, 12 Aug 2014 22:33:48 -0500 Subject: Docs: Include the concept of credentials in the high level security overview. --- docs/narr/security.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index f3879d0ba..29c62d9f3 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -13,6 +13,11 @@ authorization system can use the credentials in the :term:`request` along with the :term:`context` resource to determine if access will be allowed. Here's how it works at a high level: +- A user may or may not have previously visited the application and + supplied authentication credentials, including a :term:`userid`. If + so, the application may have called + :func:`pyramid.security.remember` to remember these. + - A :term:`request` is generated when a user visits the application. - Based on the request, a :term:`context` resource is located through @@ -25,7 +30,9 @@ allowed. Here's how it works at a high level: context as well as other attributes of the request. - If an :term:`authentication policy` is in effect, it is passed the - request; it returns some number of :term:`principal` identifiers. + request. Based on the request and the remembered (or lack of) + :term:`userid` and related credentials it returns some number of + :term:`principal` identifiers. - If an :term:`authorization policy` is in effect and the :term:`view configuration` associated with the view callable that was found has -- cgit v1.2.3 From 6bedf31e5275c2f2a33051a547aa1dc722aafa97 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Tue, 12 Aug 2014 23:05:35 -0500 Subject: Docs: Add resource tree into security overview. --- docs/narr/security.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 29c62d9f3..e6bbff44e 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -20,6 +20,12 @@ allowed. Here's how it works at a high level: - A :term:`request` is generated when a user visits the application. +- If an :term:`authorization policy` is in effect the application uses + the request and it's :term:`root factory` to create a :ref:`resource tree + ` of :term:`contexts `. The resource + tree maps contexts to URLs and within the contexts the application + puts declarations which authorize access. + - Based on the request, a :term:`context` resource is located through :term:`resource location`. A context is located differently depending on whether the application uses :term:`traversal` or :term:`URL dispatch`, but -- cgit v1.2.3 From 03e95958a9c2b9042e55bc55e4cdb193649857ef Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Tue, 12 Aug 2014 23:42:20 -0500 Subject: Docs: Switched first 2 paragraphs of security overview. --- docs/narr/security.rst | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index e6bbff44e..203962751 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -6,8 +6,18 @@ Security ======== -:app:`Pyramid` provides an optional declarative authorization system -that can prevent a :term:`view` from being invoked based on an +:app:`Pyramid` provides an optional, declarative, security system. +Security in :app:`Pyramid`, unlike many systems, cleanly and explicitly +separates authentication and authorization. Authentication is merely the +mechanism by which credentials provided in the :term:`request` are +resolved to one or more :term:`principal` identifiers. These identifiers +represent the users and groups in effect during the request. +Authorization then determines access based on the :term:`principal` +identifiers, the :term:`view callable` being invoked, and the +:term:`context` resource. + +The :app:`Pyramid` authorization system +can prevent a :term:`view` from being invoked based on an :term:`authorization policy`. Before a view is invoked, the authorization system can use the credentials in the :term:`request` along with the :term:`context` resource to determine if access will be @@ -54,14 +64,6 @@ allowed. Here's how it works at a high level: - If the authorization policy denies access, the view callable is not invoked; instead the :term:`forbidden view` is invoked. -Security in :app:`Pyramid`, unlike many systems, cleanly and explicitly -separates authentication and authorization. Authentication is merely the -mechanism by which credentials provided in the :term:`request` are -resolved to one or more :term:`principal` identifiers. These identifiers -represent the users and groups in effect during the request. -Authorization then determines access based on the :term:`principal` -identifiers, the :term:`view callable` being invoked, and the -:term:`context` resource. Authorization is enabled by modifying your application to include an :term:`authentication policy` and :term:`authorization policy`. -- cgit v1.2.3 From fe83c6bfdab16818cb434d95a09bd6510b43aa24 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 13 Aug 2014 10:48:22 -0500 Subject: some tweaks to the usage of userid in the docs --- docs/api/request.rst | 4 +-- docs/glossary.rst | 15 +++++------ docs/narr/security.rst | 69 ++++++++++++++++++++++++++++---------------------- pyramid/interfaces.py | 57 +++++++++++++++++++++++++++-------------- 4 files changed, 86 insertions(+), 59 deletions(-) diff --git a/docs/api/request.rst b/docs/api/request.rst index 4f93fa34f..dd68fa09c 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -172,8 +172,8 @@ policy` in effect or there is no currently authenticated user. This differs from :attr:`~pyramid.request.Request.unauthenticated_userid`, because the effective authentication policy will have ensured that a - record associated with the :term:`userid` exists in persistent storage; if it - has not, this value will be ``None``. + record associated with the :term:`userid` exists in persistent storage; + if it has not, this value will be ``None``. .. attribute:: unauthenticated_userid diff --git a/docs/glossary.rst b/docs/glossary.rst index eb57f3d0d..ef207a4bb 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -287,22 +287,21 @@ Glossary principal A *principal* is a string or unicode object representing an - entity, typically a user or group, having zero or more - :term:`permissions `. Principals are provided by an + entity, typically a user or group. Principals are provided by an :term:`authentication policy`. For example, if a user had the - user id "bob", and Bob was part of two groups named "group foo" + :term:`userid` `"bob"`, and was part of two groups named `"group foo"` and "group bar", the request might have information attached to it that would indicate that Bob was represented by three - principals: "bob", "group foo" and "group bar". + principals: `"bob"`, `"group foo"` and `"group bar"`. userid - A *userid* is a a string or unicode object used to identify and - authenticate a real-world user, often a person. A userid is + A *userid* is a string or unicode object used to identify and + authenticate a real-world user (or client). A userid is supplied to an :term:`authentication policy` in order to discover the user's :term:`principals `. The default behavior of the authentication policies :app:`Pyramid` provides is to - return the user's userid as one of the user's principals, but a - userid need not be a principal. + return the user's userid as a principal, but this is not strictly + necessary in custom policies that define their principals differently. authorization policy An authorization policy in :app:`Pyramid` terms is a bit of diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 203962751..2dc0c76af 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -7,14 +7,14 @@ Security ======== :app:`Pyramid` provides an optional, declarative, security system. -Security in :app:`Pyramid`, unlike many systems, cleanly and explicitly -separates authentication and authorization. Authentication is merely the -mechanism by which credentials provided in the :term:`request` are -resolved to one or more :term:`principal` identifiers. These identifiers -represent the users and groups in effect during the request. -Authorization then determines access based on the :term:`principal` -identifiers, the :term:`view callable` being invoked, and the -:term:`context` resource. +Security in :app:`Pyramid` is separated into authentication and +authorization. The two systems communicate via :term:`principal` +identifiers. Authentication is merely the mechanism by which credentials +provided in the :term:`request` are resolved to one or more +:term:`principal` identifiers. These identifiers represent the users and +groups that are in effect during the request. Authorization then determines +access based on the :term:`principal` identifiers, the requested +:term:`permission`, and a :term:`context`. The :app:`Pyramid` authorization system can prevent a :term:`view` from being invoked based on an @@ -30,12 +30,6 @@ allowed. Here's how it works at a high level: - A :term:`request` is generated when a user visits the application. -- If an :term:`authorization policy` is in effect the application uses - the request and it's :term:`root factory` to create a :ref:`resource tree - ` of :term:`contexts `. The resource - tree maps contexts to URLs and within the contexts the application - puts declarations which authorize access. - - Based on the request, a :term:`context` resource is located through :term:`resource location`. A context is located differently depending on whether the application uses :term:`traversal` or :term:`URL dispatch`, but @@ -46,9 +40,9 @@ allowed. Here's how it works at a high level: context as well as other attributes of the request. - If an :term:`authentication policy` is in effect, it is passed the - request. Based on the request and the remembered (or lack of) - :term:`userid` and related credentials it returns some number of - :term:`principal` identifiers. + request. It will return some number of :term:`principal` identifiers. + To do this, the policy would need to determine the authenticated + :term:`userid` present in the request. - If an :term:`authorization policy` is in effect and the :term:`view configuration` associated with the view callable that was found has @@ -64,7 +58,6 @@ allowed. Here's how it works at a high level: - If the authorization policy denies access, the view callable is not invoked; instead the :term:`forbidden view` is invoked. - Authorization is enabled by modifying your application to include an :term:`authentication policy` and :term:`authorization policy`. :app:`Pyramid` comes with a variety of implementations of these @@ -119,9 +112,10 @@ For example: The above configuration enables a policy which compares the value of an "auth ticket" cookie passed in the request's environment which contains a reference -to a single :term:`userid` and matches that userid's principals against the -principals present in any :term:`ACL` found in the resource tree when -attempting to call some :term:`view`. +to a single :term:`userid` and matches that userid's +:term:`principals ` against the principals present in any +:term:`ACL` found in the resource tree when attempting to call some +:term:`view`. While it is possible to mix and match different authentication and authorization policies, it is an error to configure a Pyramid application @@ -616,7 +610,9 @@ that implements the following interface: persistent store is used related to the user (the user should not have been deleted); if a record associated with the current id does not exist in a persistent store, it - should return ``None``.""" + should return ``None``. + + """ def unauthenticated_userid(self, request): """ Return the *unauthenticated* userid. This method @@ -624,24 +620,37 @@ that implements the following interface: permitted to return the userid based only on data present in the request; it needn't (and shouldn't) check any persistent store to ensure that the user record related to - the request userid exists.""" + the request userid exists. + + This method is intended primarily a helper to assist the + ``authenticated_userid`` method in pulling credentials out + of the request data, abstracting away the specific headers, + query strings, etc that are used to authenticate the request. + + """ def effective_principals(self, request): """ Return a sequence representing the effective principals - typically including the userid and any groups belonged to - by the current user, always including 'system' groups such + typically including the :term:`userid` and any groups belonged + to by the current user, always including 'system' groups such as ``pyramid.security.Everyone`` and - ``pyramid.security.Authenticated``. """ + ``pyramid.security.Authenticated``. + + """ def remember(self, request, userid, **kw): """ Return a set of headers suitable for 'remembering' the - userid named ``userid`` when set in a response. An + :term:`userid` named ``userid`` when set in a response. An individual authentication policy and its consumers can - decide on the composition and meaning of **kw. """ - + decide on the composition and meaning of **kw. + + """ + def forget(self, request): """ Return a set of headers suitable for 'forgetting' the - current user on subsequent requests. """ + current user on subsequent requests. + + """ After you do so, you can pass an instance of such a class into the :class:`~pyramid.config.Configurator.set_authentication_policy` method diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index bba818c8a..e03704b7f 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -437,38 +437,57 @@ class IViewMapperFactory(Interface): invocation signatures and response values. """ -class IAuthenticationPolicy(Interface): +class IAuthenticationPolicy(object): """ An object representing a Pyramid authentication policy. """ + def authenticated_userid(request): - """ Return the authenticated userid or ``None`` if no authenticated - userid can be found. This method of the policy should ensure that a - record exists in whatever persistent store is used related to the - user (the user should not have been deleted); if a record associated - with the current id does not exist in a persistent store, it should - return ``None``.""" + """ Return the authenticated :term:`userid` or ``None`` if + no authenticated userid can be found. This method of the + policy should ensure that a record exists in whatever + persistent store is used related to the user (the user + should not have been deleted); if a record associated with + the current id does not exist in a persistent store, it + should return ``None``. + + """ def unauthenticated_userid(request): - """ Return the *unauthenticated* userid. This method performs the - same duty as ``authenticated_userid`` but is permitted to return the - userid based only on data present in the request; it needn't (and - shouldn't) check any persistent store to ensure that the user record - related to the request userid exists.""" + """ Return the *unauthenticated* userid. This method + performs the same duty as ``authenticated_userid`` but is + permitted to return the userid based only on data present + in the request; it needn't (and shouldn't) check any + persistent store to ensure that the user record related to + the request userid exists. + + This method is intended primarily a helper to assist the + ``authenticated_userid`` method in pulling credentials out + of the request data, abstracting away the specific headers, + query strings, etc that are used to authenticate the request. + + """ def effective_principals(request): """ Return a sequence representing the effective principals - including the userid and any groups belonged to by the current - user, including 'system' groups such as Everyone and - Authenticated. """ + typically including the :term:`userid` and any groups belonged + to by the current user, always including 'system' groups such + as ``pyramid.security.Everyone`` and + ``pyramid.security.Authenticated``. + + """ def remember(request, userid, **kw): """ Return a set of headers suitable for 'remembering' the - userid named ``userid`` when set in a response. An - individual authentication policy and its consumers can decide - on the composition and meaning of ``**kw.`` """ + :term:`userid` named ``userid`` when set in a response. An + individual authentication policy and its consumers can + decide on the composition and meaning of **kw. + + """ def forget(request): """ Return a set of headers suitable for 'forgetting' the - current user on subsequent requests. """ + current user on subsequent requests. + + """ class IAuthorizationPolicy(Interface): """ An object representing a Pyramid authorization policy. """ -- cgit v1.2.3 From a9fb5255cedeb02e5c4210b90fe9942c9dbc781a Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 10 Nov 2014 01:33:22 -0600 Subject: re-add missing Interface parent --- pyramid/interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index e03704b7f..2b56262c0 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -437,7 +437,7 @@ class IViewMapperFactory(Interface): invocation signatures and response values. """ -class IAuthenticationPolicy(object): +class IAuthenticationPolicy(Interface): """ An object representing a Pyramid authentication policy. """ def authenticated_userid(request): -- cgit v1.2.3 From 7a2b72c2ba018d6b75ee151843e37da67bbfc2bb Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 10 Nov 2014 01:34:38 -0600 Subject: update the public api for remember --- docs/api/security.rst | 2 +- pyramid/security.py | 21 ++++++++++++++++++++- pyramid/tests/test_security.py | 17 +++++++++++++++-- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/docs/api/security.rst b/docs/api/security.rst index 814b68e5a..88086dbbf 100644 --- a/docs/api/security.rst +++ b/docs/api/security.rst @@ -16,7 +16,7 @@ Authentication API Functions .. autofunction:: forget -.. autofunction:: remember +.. autofunction:: remember(request, userid, **kwargs) Authorization API Functions --------------------------- diff --git a/pyramid/security.py b/pyramid/security.py index 3cef7ee5a..cbb4b895f 100644 --- a/pyramid/security.py +++ b/pyramid/security.py @@ -17,6 +17,8 @@ Authenticated = 'system.Authenticated' Allow = 'Allow' Deny = 'Deny' +_marker = object() + class AllPermissionsList(object): """ Stand in 'permission list' to represent all permissions """ def __iter__(self): @@ -115,7 +117,7 @@ deprecated( '"effective_principals" attribute of the Pyramid request instead.' ) -def remember(request, userid, **kw): +def remember(request, userid=_marker, **kw): """ Returns a sequence of header tuples (e.g. ``[('Set-Cookie', 'foo=abc')]``) on this request's response. @@ -138,7 +140,24 @@ def remember(request, userid, **kw): always return an empty sequence. If used, the composition and meaning of ``**kw`` must be agreed upon by the calling code and the effective authentication policy. + + .. deprecated:: 1.6 + Renamed the ``principal`` argument to ``userid`` to clarify its + purpose. """ + if userid is _marker: + principal = kw.pop('principal', _marker) + if principal is _marker: + raise TypeError( + 'remember() missing 1 required positional argument: ' + '\'userid\'') + else: + deprecated( + 'principal', + 'The "principal" argument was deprecated in Pyramid 1.6. ' + 'It will be removed in Pyramid 1.9. Use the "userid" ' + 'argument instead.') + userid = principal policy = _get_authentication_policy(request) if policy is None: return [] diff --git a/pyramid/tests/test_security.py b/pyramid/tests/test_security.py index 027f9cda0..6d75ac8e3 100644 --- a/pyramid/tests/test_security.py +++ b/pyramid/tests/test_security.py @@ -134,9 +134,9 @@ class TestRemember(unittest.TestCase): def tearDown(self): testing.tearDown() - def _callFUT(self, *arg): + def _callFUT(self, *arg, **kwarg): from pyramid.security import remember - return remember(*arg) + return remember(*arg, **kwarg) def test_no_authentication_policy(self): request = _makeRequest() @@ -159,6 +159,19 @@ class TestRemember(unittest.TestCase): result = self._callFUT(request, 'me') self.assertEqual(result, [('X-Pyramid-Test', 'me')]) + def test_with_deprecated_principal_arg(self): + request = _makeRequest() + registry = request.registry + _registerAuthenticationPolicy(registry, 'yo') + result = self._callFUT(request, principal='me') + self.assertEqual(result, [('X-Pyramid-Test', 'me')]) + + def test_with_missing_arg(self): + request = _makeRequest() + registry = request.registry + _registerAuthenticationPolicy(registry, 'yo') + self.assertRaises(TypeError, lambda: self._callFUT(request)) + class TestForget(unittest.TestCase): def setUp(self): testing.setUp() -- cgit v1.2.3 From 3ffd40c295a1e37ec94b6123fff8fb4dd5f5abf5 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 10 Nov 2014 01:39:53 -0600 Subject: update changelog --- CHANGES.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index c1b729b3f..8083113ef 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -55,6 +55,13 @@ Bug Fixes add another callback to the list. See https://github.com/Pylons/pyramid/pull/1373 +Deprecations +------------ + +- Renamed the ``principal`` argument to ``pyramid.security.remember()`` to + ``userid`` in order to clarify its intended purpose. + See https://github.com/Pylons/pyramid/pull/1399 + Docs ---- @@ -65,6 +72,10 @@ Docs - Clarify a previously-implied detail of the ``ISession.invalidate`` API documentation. +- Improve and clarify the documentation on what Pyramid defines as a + ``principal`` and a ``userid`` in its security APIs. + See https://github.com/Pylons/pyramid/pull/1399 + Scaffolds --------- -- cgit v1.2.3 From 6beffc41634844f3ea3b6152f292d3dbe6b5500c Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Mon, 17 Nov 2014 01:29:25 -0600 Subject: note the deprecation in the todo --- TODO.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TODO.txt b/TODO.txt index 62b8c39f4..e738b58d8 100644 --- a/TODO.txt +++ b/TODO.txt @@ -125,7 +125,10 @@ Future - 1.7: Change ``pyramid.authentication.AuthTktAuthenticationPolicy`` default ``hashalg`` to ``sha512``. -- 1.8 Remove set_request_property. +- 1.8: Remove set_request_property. + +- 1.9: Remove extra code enabling ``pyramid.security.remember(principal=...)`` + and force use of ``userid``. Probably Bad Ideas ------------------ -- cgit v1.2.3