From 0168300b0da3c79e05ec87aa777e04674a86cebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Sat, 14 Dec 2019 13:32:07 -0500 Subject: start reworking security policy --- docs/api/request.rst | 18 ++++----- docs/glossary.rst | 4 +- docs/narr/security.rst | 70 ++++++++++++++++++++-------------- docs/quick_tutorial/authentication.rst | 2 + docs/whatsnew-2.0.rst | 10 +++-- 5 files changed, 61 insertions(+), 43 deletions(-) (limited to 'docs') diff --git a/docs/api/request.rst b/docs/api/request.rst index 8e0f77b87..fb4b5caee 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -166,11 +166,11 @@ .. attribute:: authenticated_userid - .. deprecated:: 2.0 + .. versionchanged:: 2.0 - ``authenticated_userid`` has been replaced by - :attr:`authenticated_identity` in the new security system. See - :ref:`upgrading_auth` for more information. + ``authenticated_userid`` uses security policy or authn pol + see also :attr:`authenticated_identity` and + :ref:`upgrading_auth` for more information. A property which returns the :term:`userid` of the currently authenticated user or ``None`` if there is no :term:`authentication @@ -184,9 +184,9 @@ .. deprecated:: 2.0 - ``unauthenticated_userid`` has been replaced by - :attr:`authenticated_identity` in the new security system. See - :ref:`upgrading_auth` for more information. + ``unauthenticated_userid`` has been replaced by + :attr:`authenticated_identity` in the new security system. See + :ref:`upgrading_auth` for more information. A property which returns a value which represents the *claimed* (not verified) :term:`userid` of the credentials present in the @@ -203,8 +203,8 @@ .. deprecated:: 2.0 - The new security policy has removed the concept of principals. See - :ref:`upgrading_auth` for more information. + The new security policy has removed the concept of principals. See + :ref:`upgrading_auth` for more information. A property which returns the list of 'effective' :term:`principal` identifiers for this request. This list typically includes the diff --git a/docs/glossary.rst b/docs/glossary.rst index ac60ebd24..5edc4eeab 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -304,8 +304,8 @@ Glossary identity An identity is an object identifying the user associated with the - current request. The identity can be any object, but should implement a - ``__str__`` method that outputs a corresponding :term:`userid`. + current request. The identity can be any object, but security policies + should ensure that it represents a valid user (not deleted or deactivated). security policy A security policy in :app:`Pyramid` terms is an object implementing the diff --git a/docs/narr/security.rst b/docs/narr/security.rst index f1bb37c69..a71b9abd9 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -72,12 +72,19 @@ A simple security policy might look like the following: from pyramid.security import Allowed, Denied class SessionSecurityPolicy: - def identify(self, request): + def authenticated_userid(self, request): """ Return the user ID stored in the session. """ return request.session.get('userid') - def permits(self, request, context, identity, permission): + def identify(self, request): + """ Return app-specific user object. """ + userid = self.authenticated_userid(request) + if userid is not None: + return models.Users.get(id=userid) + + def permits(self, request, context, permission): """ Allow access to everything if signed in. """ + identity = self.identify(request) if identity is not None: return Allowed('User is signed in.') else: @@ -87,7 +94,7 @@ A simple security policy might look like the following: request.session['userid'] = userid return [] - def forget(request): + def forget(request, **kw): del request.session['userid'] return [] @@ -136,12 +143,16 @@ For example, our above security policy can leverage these helpers like so: def __init__(self): self.helper = SessionAuthenticationHelper() + def authenticated_userid(self, request): + # XXX add code + ... + def identify(self, request): - """ Return the user ID stored in the session. """ return self.helper.identify(request) - def permits(self, request, context, identity, permission): + def permits(self, request, context, permission): """ Allow access to everything if signed in. """ + identity = self.identify(request) if identity is not None: return Allowed('User is signed in.') else: @@ -150,8 +161,8 @@ For example, our above security policy can leverage these helpers like so: def remember(request, userid, **kw): return self.helper.remember(request, userid, **kw) - def forget(request): - return self.helper.forget(request) + def forget(request, **kw): + return self.helper.forget(request, **kw) Helpers are intended to be used with application-specific code, so perhaps your authentication also queries the database to ensure the identity is valid. @@ -159,13 +170,13 @@ authentication also queries the database to ensure the identity is valid. .. code-block:: python :linenos: - def identify(self, request): - """ Return the user ID stored in the session. """ - user_id = self.helper.identify(request) - if validate_user_id(user_id): - return user_id - else: - return None + def identify(self, request): + # XXX review: use authenticated_userid below or identify? + user_id = self.helper.identify(request) + if validate_user_id(user_id): + return user_id + else: + return None .. index:: single: permissions @@ -237,7 +248,9 @@ might look like so: from pyramid.security import Allowed, Denied class SecurityPolicy: - def permits(self, request, context, identity, permission): + def permits(self, request, context, permission): + identity = self.identify(request) + if identity is None: return Denied('User is not signed in.') if identity.role == 'admin': @@ -246,6 +259,7 @@ might look like so: allowed = ['read', 'write'] else: allowed = ['read'] + if permission in allowed: return Allowed( 'Access granted for user %s with role %s.', @@ -326,7 +340,7 @@ object. An implementation might look like this: from pyramid.authorization import ACLHelper class SecurityPolicy: - def permits(self, request, context, identity, permission): + def permits(self, request, context, permission): principals = [Everyone] if identity is not None: principals.append(Authenticated) @@ -352,7 +366,7 @@ For example, an ACL might be attached to the resource for a blog via its class: (Allow, Everyone, 'view'), (Allow, 'group:editors', 'add'), (Allow, 'group:editors', 'edit'), - ] + ] Or, if your resources are persistent, an ACL might be specified via the ``__acl__`` attribute of an *instance* of a resource: @@ -369,10 +383,10 @@ Or, if your resources are persistent, an ACL might be specified via the blog = Blog() blog.__acl__ = [ - (Allow, Everyone, 'view'), - (Allow, 'group:editors', 'add'), - (Allow, 'group:editors', 'edit'), - ] + (Allow, Everyone, 'view'), + (Allow, 'group:editors', 'add'), + (Allow, 'group:editors', 'edit'), + ] Whether an ACL is attached to a resource's class or an instance of the resource itself, the effect is the same. It is useful to decorate individual resource @@ -425,10 +439,10 @@ Here's an example ACL: from pyramid.security import Everyone __acl__ = [ - (Allow, Everyone, 'view'), - (Allow, 'group:editors', 'add'), - (Allow, 'group:editors', 'edit'), - ] + (Allow, Everyone, 'view'), + (Allow, 'group:editors', 'add'), + (Allow, 'group:editors', 'edit'), + ] The example ACL indicates that the :data:`pyramid.security.Everyone` principal—a special system-defined principal indicating, literally, everyone—is @@ -460,7 +474,7 @@ dictated by the ACL*. So if you have an ACL like this: __acl__ = [ (Allow, Everyone, 'view'), (Deny, Everyone, 'view'), - ] + ] The ACL helper will *allow* everyone the view permission, even though later in the ACL you have an ACE that denies everyone the view permission. On the other @@ -476,7 +490,7 @@ hand, if you have an ACL like this: __acl__ = [ (Deny, Everyone, 'view'), (Allow, Everyone, 'view'), - ] + ] The ACL helper will deny everyone the view permission, even though later in the ACL, there is an ACE that allows everyone. @@ -495,7 +509,7 @@ can collapse this into a single ACE, as below. __acl__ = [ (Allow, Everyone, 'view'), (Allow, 'group:editors', ('add', 'edit')), - ] + ] .. _special_principals: diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index cd038ea36..ccdd9b70b 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -104,6 +104,8 @@ Steps Analysis ======== +# TODO update + Unlike many web frameworks, Pyramid includes a built-in but optional security model for authentication and authorization. This security system is intended to be flexible and support many needs. In this security model, authentication (who diff --git a/docs/whatsnew-2.0.rst b/docs/whatsnew-2.0.rst index bf1554a27..4448e0f69 100644 --- a/docs/whatsnew-2.0.rst +++ b/docs/whatsnew-2.0.rst @@ -44,10 +44,12 @@ The new security policy adds the concept of an :term:`identity`, which is an object representing the user associated with the current request. The identity can be accessed via :attr:`pyramid.request.Request.authenticated_identity`. The object can be of any shape, such as a simple ID string or an ORM object, -but should implement a ``__str__`` method that returns a string identifying the -current user, e.g. the ID of the user object in a database. The string -representation is return as -:attr:`pyramid.request.Request.authenticated_userid`. +and should represent an active user. + +As in previous version, the property :attr:`pyramid.request.Request.authenticated_userid` +can be used to get a string identifying the current user, for example +the ID of the user object in a database. The value is obtained from the +security policy. (:attr:`pyramid.request.Request.unauthenticated_userid` has been deprecated.) The concept of :term:`principals ` has been removed; the -- cgit v1.2.3 From 2cbb91b80438e6f5ec98d004eb5ac8c1650ad176 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sat, 14 Dec 2019 19:30:21 -0600 Subject: Remove TODO for authentication tutorial. It should be done, but not as part of this PR. I'll open an issue. --- docs/quick_tutorial/authentication.rst | 2 -- 1 file changed, 2 deletions(-) (limited to 'docs') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index ccdd9b70b..cd038ea36 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -104,8 +104,6 @@ Steps Analysis ======== -# TODO update - Unlike many web frameworks, Pyramid includes a built-in but optional security model for authentication and authorization. This security system is intended to be flexible and support many needs. In this security model, authentication (who -- cgit v1.2.3 From cd0b92d10bfbb38068c216ce44dde9732fa127a8 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sat, 14 Dec 2019 20:27:30 -0600 Subject: Update docs. --- docs/api/request.rst | 20 +++++-------------- docs/narr/security.rst | 54 ++++++++++++++++++++------------------------------ docs/whatsnew-2.0.rst | 19 ++++++++---------- 3 files changed, 35 insertions(+), 58 deletions(-) (limited to 'docs') diff --git a/docs/api/request.rst b/docs/api/request.rst index fb4b5caee..50703ff63 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -166,27 +166,17 @@ .. attribute:: authenticated_userid - .. versionchanged:: 2.0 - - ``authenticated_userid`` uses security policy or authn pol - see also :attr:`authenticated_identity` and - :ref:`upgrading_auth` for more information. - 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``. + authenticated user or ``None`` if there is no :term:`security policy` in + effect or there is no currently authenticated user. .. attribute:: unauthenticated_userid .. deprecated:: 2.0 - ``unauthenticated_userid`` has been replaced by - :attr:`authenticated_identity` in the new security system. See - :ref:`upgrading_auth` for more information. + ``unauthenticated_userid`` has been deprecated in version 2.0. Use + :attr:`authenticated_userid` or :attr:`authenticated_identity` + instead. See :ref:`upgrading_auth` for more information. A property which returns a value which represents the *claimed* (not verified) :term:`userid` of the credentials present in the diff --git a/docs/narr/security.rst b/docs/narr/security.rst index a71b9abd9..b01bec903 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -32,14 +32,11 @@ how it works at a high level: - A :term:`view callable` is located by :term:`view lookup` using the context as well as other attributes of the request. -- If a :term:`security policy` is in effect, it is passed the request and - returns the :term:`identity` of the current user. - - If a :term:`security policy` is in effect and the :term:`view configuration` associated with the view callable that was found has a - :term:`permission` associated with it, the policy is passed the - :term:`context`, the current :term:`identity`, and the :term:`permission` - associated with the view; it will allow or deny access. + :term:`permission` associated with it, the policy is passed :term:`request`, + the :term:`context`, and the :term:`permission` associated with the view; it + will allow or deny access. - If the security policy allows access, the view callable is invoked. @@ -62,7 +59,7 @@ Writing a Security Policy accessible by completely anonymous users. In order to begin protecting views from execution based on security settings, you need to write a security policy. -Security policies are simple classes implementing a +Security policies are simple classes implementing :class:`pyramid.interfaces.ISecurityPolicy`. A simple security policy might look like the following: @@ -72,15 +69,16 @@ A simple security policy might look like the following: from pyramid.security import Allowed, Denied class SessionSecurityPolicy: - def authenticated_userid(self, request): - """ Return the user ID stored in the session. """ - return request.session.get('userid') - def identify(self, request): """ Return app-specific user object. """ - userid = self.authenticated_userid(request) - if userid is not None: - return models.Users.get(id=userid) + userid = request.session.get('userid') + if userid is None: + return None + return load_identity_from_db(request, userid) + + def authenticated_userid(self, request): + """ Return a string ID for the user. """ + return self.identify(request).id def permits(self, request, context, permission): """ Allow access to everything if signed in. """ @@ -143,12 +141,12 @@ For example, our above security policy can leverage these helpers like so: def __init__(self): self.helper = SessionAuthenticationHelper() - def authenticated_userid(self, request): - # XXX add code - ... - def identify(self, request): - return self.helper.identify(request) + userid = self.helper.authenticated_userid(request) + return load_identity_from_db(request, userid) + + def authenticated_userid(self, request): + return self.identify(request).id def permits(self, request, context, permission): """ Allow access to everything if signed in. """ @@ -164,19 +162,11 @@ For example, our above security policy can leverage these helpers like so: def forget(request, **kw): return self.helper.forget(request, **kw) -Helpers are intended to be used with application-specific code, so perhaps your -authentication also queries the database to ensure the identity is valid. - -.. code-block:: python - :linenos: - - def identify(self, request): - # XXX review: use authenticated_userid below or identify? - user_id = self.helper.identify(request) - if validate_user_id(user_id): - return user_id - else: - return None +Helpers are intended to be used with application-specific code. Notice how the +above code takes the userid from the helper and uses it to load the +:term:`identity` from the database. ``authenticated_userid`` pulls the +:term:`userid` from the :term:`identity` in order to guarantee that the user ID +stored in the session exists in the database ("authenticated"). .. index:: single: permissions diff --git a/docs/whatsnew-2.0.rst b/docs/whatsnew-2.0.rst index b5f349166..6b3261284 100644 --- a/docs/whatsnew-2.0.rst +++ b/docs/whatsnew-2.0.rst @@ -40,17 +40,15 @@ The new security policy should implement ``security_policy`` argument of :class:`pyramid.config.Configurator` or :meth:`pyramid.config.Configurator.set_security_policy`. +The policy contains ``authenticated_userid`` and ``remember``, +with the same method signatures as in the legacy authentication policy. It +also contains ``forget``, but now with keyword arguments in the method +signature. + The new security policy adds the concept of an :term:`identity`, which is an object representing the user associated with the current request. The identity can be accessed via :attr:`pyramid.request.Request.authenticated_identity`. -The object can be of any shape, such as a simple ID string or an ORM object, -and should represent an active user. - -As in previous version, the property :attr:`pyramid.request.Request.authenticated_userid` -can be used to get a string identifying the current user, for example -the ID of the user object in a database. The value is obtained from the -security policy. -(:attr:`pyramid.request.Request.unauthenticated_userid` has been deprecated.) +The object can be of any shape, such as a simple ID string or an ORM object. The concept of :term:`principals ` has been removed; the ``permits`` method is passed an identity object. This change gives much more @@ -97,9 +95,8 @@ The new :attr:`pyramid.request.Request.authenticated_identity` property will output the same result as :attr:`pyramid.request.Request.authenticated_userid`. If using a security policy, -:attr:`pyramid.request.Request.unauthenticated_userid` and -:attr:`pyramid.request.Request.authenticated_userid` will both return the -string representation of the :term:`identity`. +:attr:`pyramid.request.Request.authenticated_userid` will return the same value +as :attr:`pyramid.request.Request.authenticated_userid`. :attr:`pyramid.request.Request.effective_principals` will always return a one-element list containing the :data:`pyramid.security.Everyone` principal, as there is no equivalent in the new security policy. -- cgit v1.2.3 From 2e06fa414412688dc3b7e0b422b0fc0b96ec882f Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sat, 14 Dec 2019 20:17:36 -0800 Subject: Bring back identity into permits. --- docs/narr/security.rst | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'docs') diff --git a/docs/narr/security.rst b/docs/narr/security.rst index b01bec903..07b7fe825 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -80,9 +80,8 @@ A simple security policy might look like the following: """ Return a string ID for the user. """ return self.identify(request).id - def permits(self, request, context, permission): + def permits(self, request, context, identity, permission): """ Allow access to everything if signed in. """ - identity = self.identify(request) if identity is not None: return Allowed('User is signed in.') else: @@ -148,9 +147,8 @@ For example, our above security policy can leverage these helpers like so: def authenticated_userid(self, request): return self.identify(request).id - def permits(self, request, context, permission): + def permits(self, request, context, identity, permission): """ Allow access to everything if signed in. """ - identity = self.identify(request) if identity is not None: return Allowed('User is signed in.') else: @@ -238,9 +236,7 @@ might look like so: from pyramid.security import Allowed, Denied class SecurityPolicy: - def permits(self, request, context, permission): - identity = self.identify(request) - + def permits(self, request, context, identity, permission): if identity is None: return Denied('User is not signed in.') if identity.role == 'admin': @@ -330,7 +326,7 @@ object. An implementation might look like this: from pyramid.authorization import ACLHelper class SecurityPolicy: - def permits(self, request, context, permission): + def permits(self, request, context, identity, permission): principals = [Everyone] if identity is not None: principals.append(Authenticated) -- cgit v1.2.3 From 8a93507edf5032334b597f47c4e520a2ef08b2d8 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sun, 15 Dec 2019 08:53:04 -0800 Subject: Update docs/narr/security.rst Co-Authored-By: Steve Piercy --- docs/narr/security.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 07b7fe825..aac9eeb7b 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -35,7 +35,7 @@ how it works at a high level: - If a :term:`security policy` is in effect and the :term:`view configuration` associated with the view callable that was found has a :term:`permission` associated with it, the policy is passed :term:`request`, - the :term:`context`, and the :term:`permission` associated with the view; it + the :term:`context`, and the :term:`permission` associated with the view; it will allow or deny access. - If the security policy allows access, the view callable is invoked. -- cgit v1.2.3 From 7b74e97fd156bef6b8f347d7d38615d5bea6c967 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sun, 15 Dec 2019 09:15:12 -0800 Subject: Four spaces of indentation. --- docs/api/request.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/api/request.rst b/docs/api/request.rst index 50703ff63..9e9c70d3a 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -174,9 +174,9 @@ .. deprecated:: 2.0 - ``unauthenticated_userid`` has been deprecated in version 2.0. Use - :attr:`authenticated_userid` or :attr:`authenticated_identity` - instead. See :ref:`upgrading_auth` for more information. + ``unauthenticated_userid`` has been deprecated in version 2.0. Use + :attr:`authenticated_userid` or :attr:`authenticated_identity` + instead. See :ref:`upgrading_auth` for more information. A property which returns a value which represents the *claimed* (not verified) :term:`userid` of the credentials present in the @@ -193,8 +193,8 @@ .. deprecated:: 2.0 - The new security policy has removed the concept of principals. See - :ref:`upgrading_auth` for more information. + The new security policy has removed the concept of principals. See + :ref:`upgrading_auth` for more information. A property which returns the list of 'effective' :term:`principal` identifiers for this request. This list typically includes the -- cgit v1.2.3 From 32bf9b3669f2ba0c4a0aaf35f4e2cdad8f9314f0 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sun, 15 Dec 2019 19:55:10 -0800 Subject: Revert "Bring back identity into permits." This reverts commit 2e06fa414412688dc3b7e0b422b0fc0b96ec882f. --- docs/narr/security.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/narr/security.rst b/docs/narr/security.rst index aac9eeb7b..cdc16b6a1 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -80,8 +80,9 @@ A simple security policy might look like the following: """ Return a string ID for the user. """ return self.identify(request).id - def permits(self, request, context, identity, permission): + def permits(self, request, context, permission): """ Allow access to everything if signed in. """ + identity = self.identify(request) if identity is not None: return Allowed('User is signed in.') else: @@ -147,8 +148,9 @@ For example, our above security policy can leverage these helpers like so: def authenticated_userid(self, request): return self.identify(request).id - def permits(self, request, context, identity, permission): + def permits(self, request, context, permission): """ Allow access to everything if signed in. """ + identity = self.identify(request) if identity is not None: return Allowed('User is signed in.') else: @@ -236,7 +238,9 @@ might look like so: from pyramid.security import Allowed, Denied class SecurityPolicy: - def permits(self, request, context, identity, permission): + def permits(self, request, context, permission): + identity = self.identify(request) + if identity is None: return Denied('User is not signed in.') if identity.role == 'admin': @@ -326,7 +330,7 @@ object. An implementation might look like this: from pyramid.authorization import ACLHelper class SecurityPolicy: - def permits(self, request, context, identity, permission): + def permits(self, request, context, permission): principals = [Everyone] if identity is not None: principals.append(Authenticated) -- cgit v1.2.3 From 11b3c1c7dea42f8290b6a91d5ab292a27d974f3b Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sun, 15 Dec 2019 20:02:36 -0800 Subject: Fix whatsnew. --- docs/whatsnew-2.0.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/whatsnew-2.0.rst b/docs/whatsnew-2.0.rst index 6b3261284..d5f825c43 100644 --- a/docs/whatsnew-2.0.rst +++ b/docs/whatsnew-2.0.rst @@ -94,9 +94,5 @@ normal, as well as all related :class:`pyramid.request.Request` properties. The new :attr:`pyramid.request.Request.authenticated_identity` property will output the same result as :attr:`pyramid.request.Request.authenticated_userid`. -If using a security policy, -:attr:`pyramid.request.Request.authenticated_userid` will return the same value -as :attr:`pyramid.request.Request.authenticated_userid`. -:attr:`pyramid.request.Request.effective_principals` will always return a -one-element list containing the :data:`pyramid.security.Everyone` principal, as -there is no equivalent in the new security policy. +If using a security policy, :attr:`pyramid.request.Request.unauthenticated_userid` will return the same value as :attr:`pyramid.request.Request.authenticated_userid`. +:attr:`pyramid.request.Request.effective_principals` will always return a one-element list containing the :data:`pyramid.security.Everyone` principal, as there is no equivalent in the new security policy. -- cgit v1.2.3 From 5f6f7184a997cb2dfa341eef53259d4254a242e8 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Sun, 15 Dec 2019 20:27:10 -0800 Subject: Remove requirement that identity is validated. --- docs/glossary.rst | 5 ++--- docs/narr/security.rst | 28 +++++++++++++++++++--------- 2 files changed, 21 insertions(+), 12 deletions(-) (limited to 'docs') diff --git a/docs/glossary.rst b/docs/glossary.rst index 5edc4eeab..8152c7b96 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -303,9 +303,8 @@ Glossary request. Oftentimes this is the ID of the user object in a database. identity - An identity is an object identifying the user associated with the - current request. The identity can be any object, but security policies - should ensure that it represents a valid user (not deleted or deactivated). + An identity is an object identifying the user associated with the current request. + The object can be of any shape, such as a simple ID string or an ORM object. security policy A security policy in :app:`Pyramid` terms is an object implementing the diff --git a/docs/narr/security.rst b/docs/narr/security.rst index cdc16b6a1..60be067bf 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -69,17 +69,21 @@ A simple security policy might look like the following: from pyramid.security import Allowed, Denied class SessionSecurityPolicy: + def authenticated_userid(self, request): + """ Return a string ID for the user. """ + userid = self.identify(request).id + if validate_userid(request, userid): + return userid + else: + return None + def identify(self, request): """ Return app-specific user object. """ - userid = request.session.get('userid') + userid = self.authenticated_userid if userid is None: return None return load_identity_from_db(request, userid) - def authenticated_userid(self, request): - """ Return a string ID for the user. """ - return self.identify(request).id - def permits(self, request, context, permission): """ Allow access to everything if signed in. """ identity = self.identify(request) @@ -141,12 +145,18 @@ For example, our above security policy can leverage these helpers like so: def __init__(self): self.helper = SessionAuthenticationHelper() - def identify(self, request): + def authenticated_userid(self, request): userid = self.helper.authenticated_userid(request) - return load_identity_from_db(request, userid) + if validate_userid(request, userid): + return userid + else: + return None - def authenticated_userid(self, request): - return self.identify(request).id + def identify(self, request): + userid = self.authenticated_userid + if userid is None: + return None + return load_identity_from_db(request, userid) def permits(self, request, context, permission): """ Allow access to everything if signed in. """ -- cgit v1.2.3 From 918155824ec9bdd8f7a08c1b0a3e0c56720e9f41 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Mon, 16 Dec 2019 17:30:43 -0800 Subject: Update docs/narr/security.rst code examples. --- docs/narr/security.rst | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'docs') diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 60be067bf..50eeab27b 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -69,21 +69,20 @@ A simple security policy might look like the following: from pyramid.security import Allowed, Denied class SessionSecurityPolicy: - def authenticated_userid(self, request): - """ Return a string ID for the user. """ - userid = self.identify(request).id - if validate_userid(request, userid): - return userid - else: - return None - def identify(self, request): """ Return app-specific user object. """ - userid = self.authenticated_userid + userid = request.session.get('userid') if userid is None: return None return load_identity_from_db(request, userid) + def authenticated_userid(self, request): + """ Return a string ID for the user. """ + identity = request.authenticated_identity + if identity is None: + return None + return string(identity.id) + def permits(self, request, context, permission): """ Allow access to everything if signed in. """ identity = self.identify(request) @@ -145,19 +144,20 @@ For example, our above security policy can leverage these helpers like so: def __init__(self): self.helper = SessionAuthenticationHelper() - def authenticated_userid(self, request): - userid = self.helper.authenticated_userid(request) - if validate_userid(request, userid): - return userid - else: - return None - def identify(self, request): - userid = self.authenticated_userid + """ Return app-specific user object. """ + userid = self.helper.authenticated_userid(request) if userid is None: return None return load_identity_from_db(request, userid) + def authenticated_userid(self, request): + """ Return a string ID for the user. """ + identity = request.authenticated_identity + if identity is None: + return None + return str(identity.id) + def permits(self, request, context, permission): """ Allow access to everything if signed in. """ identity = self.identify(request) -- cgit v1.2.3 From 014b5ecedec76fd7bbade6c954adce94954bd171 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Tue, 17 Dec 2019 11:33:18 -0800 Subject: Use `self.identify` instead of `request.authenticated_identity` --- docs/narr/security.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 50eeab27b..ac64cba0a 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -78,7 +78,7 @@ A simple security policy might look like the following: def authenticated_userid(self, request): """ Return a string ID for the user. """ - identity = request.authenticated_identity + identity = self.identify(request) if identity is None: return None return string(identity.id) @@ -153,7 +153,7 @@ For example, our above security policy can leverage these helpers like so: def authenticated_userid(self, request): """ Return a string ID for the user. """ - identity = request.authenticated_identity + identity = self.identify(request) if identity is None: return None return str(identity.id) -- cgit v1.2.3