
:LastChangedDate: $LastChangedDate$
:LastChangedRevision: $LastChangedRevision$
:LastChangedBy: $LastChangedBy$

Authentication with Perspective Broker
======================================








Overview
--------



The examples shown in :doc:`Using Perspective Broker <pb-usage>` demonstrate how to do basic remote method calls, but provided no
facilities for authentication. In this context, authentication is about who
gets which remote references, and how to restrict access to the "right" 
set of people or programs.




As soon as you have a program which offers services to multiple users,
where those users should not be allowed to interfere with each other, you
need to think about authentication. Many services use the idea of an "account" , and rely upon fact that each user has access to only one
account. Twisted uses a system called :doc:`cred <cred>` to
handle authentication issues, and Perspective Broker has code to make it
easy to implement the most common use cases.





Compartmentalizing Services
---------------------------



Imagine how you would write a chat server using PB. The first step might
be a ``ChatServer`` object which had a bunch of 
``pb.RemoteReference`` s that point at user clients. Pretend that
those clients offered a ``remote_print`` method which lets the
server print a message on the user's console. In that case, the server might
look something like this:





.. code-block:: python

    
    class ChatServer(pb.Referenceable):
    
        def __init__(self):
            self.groups = {} # indexed by name
            self.users = {} # indexed by name
        def remote_joinGroup(self, username, groupname):
            if not self.groups.has_key(groupname):
                self.groups[groupname] = []
            self.groups[groupname].append(self.users[username])
        def remote_sendMessage(self, from_username, groupname, message):
            group = self.groups[groupname]
            if group:
                # send the message to all members of the group
                for user in group:
                    user.callRemote("print",
                                    "<%s> says: %s" % (from_username,
                                                             message))




For now, assume that all clients have somehow acquired a 
``pb.RemoteReference`` to this ``ChatServer`` object,
perhaps using ``pb.Root`` and ``getRootObject`` as
described in the :doc:`previous chapter <pb-usage>` . In this
scheme, when a user sends a message to the group, their client runs
something like the following:





.. code-block:: python

    
    remotegroup.callRemote("sendMessage", "alice", "Hi, my name is alice.")






Incorrect Arguments
~~~~~~~~~~~~~~~~~~~



You've probably seen the first problem: users can trivially spoof each
other. We depend upon the user to pass a correct value in their
"username" argument, and have no way to tell if they're lying or not.
There is nothing to prevent Alice from modifying her client to do:





.. code-block:: python

    
    remotegroup.callRemote("sendMessage", "bob", "i like pork")




much to the horror of Bob's vegetarian friends. [#]_ 




(In general, learn to get suspicious if you see any argument of a
remotely-invokable method described as "must be X" )




The best way to fix this is to keep track of the user's name locally,
rather than asking them to send it to the server with each message. The best
place to keep state is in an object, so this suggests we need a per-user
object. Rather than choosing an obvious name [#]_ , let's call this the 
``User`` class.





.. code-block:: python

    
    class User(pb.Referenceable):
        def __init__(self, username, server, clientref):
            self.name = username
            self.server = server
            self.remote = clientref
        def remote_joinGroup(self, groupname):
            self.server.joinGroup(groupname, self)
        def remote_sendMessage(self, groupname, message):
            self.server.sendMessage(self.name, groupname, message)
        def send(self, message):
            self.remote.callRemote("print", message)
    
    class ChatServer:
        def __init__(self):
            self.groups = {} # indexed by name
        def joinGroup(self, groupname, user):
            if not self.groups.has_key(groupname):
                self.groups[groupname] = []
            self.groups[groupname].append(user)
        def sendMessage(self, from_username, groupname, message):
            group = self.groups[groupname]
            if group:
                # send the message to all members of the group
                for user in group:
                    user.send("<%s> says: %s" % (from_username, message))




Again, assume that each remote client gets access to a single 
``User`` object, which is created with the proper username.




Note how the ``ChatServer`` object has no remote access: it
isn't even ``pb.Referenceable`` anymore. This means that all access
to it must be mediated through other objects, with code that is under your
control.




As long as Alice only has access to her own ``User`` object, she
can no longer spoof Bob. The only way for her to invoke 
``ChatServer.sendMessage`` is to call her ``User`` 
object's ``remote_sendMessage`` method, and that method uses its
own state to provide the ``from_username`` argument. It doesn't
give her any way to change that state.




This restriction is important. The ``User`` object is able to
maintain its own integrity because there is a wall between the object and
the client: the client cannot inspect or modify internal state, like the 
``.name`` attribute. The only way through this wall is via remote
method invocations, and the only control Alice has over those invocations is
when they get invoked and what arguments they are given.



.. note::
   
   
   No object can maintain its integrity against local threats: by design,
   Python offers no mechanism for class instances to hide their attributes, and
   once an intruder has a copy of ``self.__dict__`` , they can do
   everything the original object was able to do.
   
   






Unforgeable References
~~~~~~~~~~~~~~~~~~~~~~



Now suppose you wanted to implement group parameters, for example a mode
in which nobody was allowed to talk about mattresses because some users were
sensitive and calming them down after someone said "mattress" is a
hassle that's best avoided altogether. Again, per-group state implies a
per-group object. We'll go out on a limb and call this the 
``Group`` object:





.. code-block:: python

    
    class User(pb.Referenceable):
        def __init__(self, username, server, clientref):
            self.name = username
            self.server = server
            self.remote = clientref
        def remote_joinGroup(self, groupname, allowMattress=True):
            return self.server.joinGroup(groupname, self, allowMattress)
        def send(self, message):
            self.remote.callRemote("print", message)
    
    class Group(pb.Referenceable):
        def __init__(self, groupname, allowMattress):
            self.name = groupname
            self.allowMattress = al                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        